Skip to content

Commit 6179225

Browse files
Charly-sketchnedseb
authored andcommitted
lis2mdl: add driver
1 parent d78202c commit 6179225

5 files changed

Lines changed: 1142 additions & 121 deletions

File tree

lib/lis2mdl/README.md

Lines changed: 254 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,274 @@
1-
# LIS2MDL Magnetometer Driver
1+
# LIS2MDL Magnetometer Driver for MicroPython
22

3-
This is a MicroPython driver for the LIS2MDL 3-axis magnetometer. The LIS2MDL is a high-performance magnetic sensor designed for applications such as electronic compasses, motion tracking, and orientation detection. This driver provides methods for initialization, calibration, and reading magnetic field data.
3+
A complete and feature-rich driver for the **LIS2MDL 3-axis magnetometer** by STMicroelectronics.
4+
This library allows easy integration of the LIS2MDL sensor with MicroPython or CircuitPython boards using I²C.
5+
It provides low-level register access, automatic calibration, heading computation, and tilt compensation — ideal for **digital compasses**, **robot navigation**, and **orientation tracking**.
46

5-
## Features
6-
- Soft reset and initialization of the LIS2MDL sensor.
7-
- Configurable output data rate (ODR) and low-power mode.
8-
- 3D calibration for offsets and scales.
9-
- Heading calculation with and without tilt compensation.
10-
- Direction labeling (e.g., N, NE, E, etc.).
7+
---
118

12-
## Requirements
13-
- MicroPython-compatible board with I2C support.
14-
- LIS2MDL sensor module.
9+
## 🧭 Features
1510

16-
## Installation
17-
1. Copy the `lis2mdl` folder to your MicroPython device.
18-
2. Import the driver in your script:
19-
```python
20-
from lis2mdl.device import LIS2MDL
21-
```
11+
* ✅ Full **I²C driver** for LIS2MDL
12+
* ✅ Supports **10 / 20 / 50 / 100 Hz** output data rates
13+
***Temperature-compensated** and **low-power** modes
14+
* ✅ Read **raw**, **scaled**, or **calibrated** magnetic field data
15+
***2D and 3D calibration** routines (auto min/max method)
16+
***Heading computation** (flat or tilt-compensated)
17+
***Compass direction labels** (N, NE, E, …)
18+
* ✅ Built-in **digital low-pass filter** and **offset cancellation** control
19+
* ✅ Diagnostic utilities:
20+
21+
* Register dump
22+
* Calibration quality metrics
23+
* Self-test and temperature readout
24+
25+
---
26+
27+
## ⚙️ Hardware Requirements
28+
29+
* **LIS2MDL** 3-axis magnetometer (STMicroelectronics)
30+
* **MicroPython/CircuitPython board**, e.g.:
31+
32+
* ESP32 / ESP8266
33+
* Raspberry Pi Pico / RP2040
34+
* STM32 Nucleo or Pyboard
35+
* 3.3V power supply
36+
* I²C interface (SCL, SDA)
37+
38+
---
39+
40+
## 🔌 Wiring Example (ESP32)
41+
42+
| LIS2MDL Pin | ESP32 Pin | Description |
43+
| ----------- | --------- | ------------ |
44+
| VIN | 3.3V | Power supply |
45+
| GND | GND | Ground |
46+
| SDA | GPIO21 | I²C Data |
47+
| SCL | GPIO22 | I²C Clock |
48+
49+
Example setup:
2250

23-
## Usage
24-
### Basic Example
2551
```python
26-
from time import sleep_ms
27-
from machine import I2C
28-
from lis2mdl.device import LIS2MDL
52+
from machine import I2C, Pin
53+
from device import LIS2MDL
2954

30-
# Initialize I2C and LIS2MDL
31-
i2c = I2C(1)
55+
i2c = I2C(1, scl=Pin(22), sda=Pin(21))
3256
mag = LIS2MDL(i2c)
57+
```
3358

34-
# Perform calibration
35-
mag.calibrate_step()
36-
calibration_values = mag.get_calibration()
37-
print("Calibration values:", calibration_values)
59+
---
3860

39-
# Continuous heading reading
40-
print("Continuous heading readings:")
41-
while True:
42-
angle = mag.heading_flat_only()
43-
direction = mag.direction_label(angle)
44-
print(f"{direction} | angle={angle:.2f}°")
45-
sleep_ms(100)
61+
## 🧩 Installation
62+
63+
### 1. Copy files to your board
64+
65+
Upload both files using Thonny, mpremote, or ampy:
66+
67+
```
68+
device.py
69+
lis2mdl/const.py
4670
```
4771

48-
### Tilt Compensation Example
49-
To use tilt compensation, you need an accelerometer to provide roll and pitch data. Pass a function that reads accelerometer data to the `heading_with_tilt_compensation` method.
72+
### 2. Import and initialize
73+
74+
```python
75+
from machine import I2C, Pin
76+
from device import LIS2MDL
77+
78+
i2c = I2C(1, scl=Pin(22), sda=Pin(21))
79+
mag = LIS2MDL(i2c)
80+
```
81+
82+
---
83+
84+
## 🚀 Quick Start
85+
86+
### Read magnetic field
87+
88+
```python
89+
x, y, z = mag.read_magnet_uT()
90+
print("Magnetic field (µT):", x, y, z)
91+
```
92+
93+
### Get heading (flat orientation)
94+
95+
```python
96+
heading = mag.heading_flat_only()
97+
print("Heading: {:.1f}° {}".format(heading, mag.direction_label(heading)))
98+
```
99+
100+
### With tilt compensation
101+
102+
Requires a function returning accelerometer data `(ax, ay, az)` in g:
50103

51104
```python
52105
def read_accel():
53-
# Replace with your accelerometer reading logic
54-
return ax, ay, az
106+
return (0.0, 0.0, 1.0) # Example static vector
107+
108+
heading = mag.heading_with_tilt_compensation(read_accel)
109+
```
110+
111+
---
112+
113+
## ⚖️ Calibration
114+
115+
Calibration is essential to obtain accurate compass readings.
116+
The driver provides **automated routines** for both 2D (flat) and 3D calibration.
117+
118+
### 2D Calibration (Flat)
119+
120+
Rotate the board **horizontally** in all directions:
121+
122+
```python
123+
mag.calibrate_minmax_2d(samples=300)
124+
```
125+
126+
### 3D Calibration (Full)
55127

56-
angle = mag.heading_with_tilt_compensation(read_accel)
57-
print(f"Tilt-compensated angle: {angle:.2f}°")
128+
Rotate the board **in all orientations**:
129+
130+
```python
131+
mag.calibrate_minmax_3d(samples=600)
132+
```
133+
134+
### Apply and test calibration
135+
136+
```python
137+
print("Calibration:", mag.read_calibration())
138+
quality = mag.calibrate_quality()
139+
print("Quality metrics:", quality)
140+
```
141+
142+
### Reset calibration
143+
144+
```python
145+
mag.calibrate_reset()
58146
```
59147

60-
## Calibration
61-
The `calibrate_step` method performs a quick 3D calibration. Rotate the sensor flat over 360° to capture the minimum and maximum magnetic field values. The offsets and scales are calculated automatically.
148+
---
149+
150+
## 🧰 Configuration Examples
151+
152+
### Output rate and power
153+
154+
```python
155+
mag.set_odr(50) # 50 Hz
156+
mag.set_low_power(True) # Enable low-power mode
157+
```
158+
159+
### Enable digital low-pass filter
160+
161+
```python
162+
mag.set_low_pass(True)
163+
```
164+
165+
### Configure declination and heading offset
166+
167+
```python
168+
mag.set_declination(1.5) # Magnetic declination (°)
169+
mag.set_heading_offset(-5.0) # Align physical 0°
170+
```
171+
172+
### Block data update (BDU)
173+
174+
```python
175+
mag.set_bdu(True)
176+
```
177+
178+
---
179+
180+
## 🧮 Heading Filtering
181+
182+
You can apply a **smoothing filter** on the heading angle to stabilize the readings:
183+
184+
```python
185+
mag.set_heading_filter(alpha=0.2) # Light smoothing
186+
```
187+
188+
* `alpha = 0.0` → no filter
189+
* `alpha = 0.1–0.3` → medium smoothing
190+
* `alpha = 1.0` → very heavy smoothing
191+
192+
---
193+
194+
## 🔍 Diagnostics & Debug
195+
196+
### Read sensor ID
197+
198+
```python
199+
print("WHO_AM_I:", hex(mag.read_who_am_i()))
200+
```
201+
202+
Expected value: `0x40`
203+
204+
### Read temperature (approximate)
205+
206+
```python
207+
print("Temperature (°C):", mag.read_temperature_c())
208+
```
209+
210+
### Check data readiness
211+
212+
```python
213+
if mag.data_ready():
214+
print("New magnetic data available!")
215+
```
216+
217+
### Dump consecutive registers
218+
219+
```python
220+
regs = mag.read_registers(0x60, 12)
221+
print("Register dump:", regs)
222+
```
223+
224+
---
225+
226+
## 🧠 Internal Methods Overview
227+
228+
| Method | Description |
229+
| ---------------------------------- | ------------------------------ |
230+
| `read_magnet_raw()` | Raw sensor values (int16) |
231+
| `read_magnet_uT()` | Magnetic field in µT |
232+
| `read_magnet_calibrated_norm()` | Calibrated and normalized data |
233+
| `heading_flat_only()` | Flat compass heading |
234+
| `heading_with_tilt_compensation()` | Tilt-corrected heading |
235+
| `read_temperature_c()` | Read relative temperature |
236+
| `power_down()` / `wake()` | Power management |
237+
| `soft_reset()` / `reboot()` | Sensor reset functions |
238+
239+
---
240+
241+
## 🧪 Example: Continuous Compass Loop
242+
243+
```python
244+
from machine import I2C, Pin
245+
from device import LIS2MDL
246+
import time
247+
248+
i2c = I2C(1, scl=Pin(22), sda=Pin(21))
249+
mag = LIS2MDL(i2c)
250+
mag.set_declination(2.3)
251+
252+
while True:
253+
heading = mag.heading_flat_only()
254+
print("Heading: {:.1f}° {}".format(heading, mag.direction_label(heading)))
255+
time.sleep(0.5)
256+
```
257+
258+
---
259+
260+
## 🧾 Notes
261+
262+
* The LIS2MDL outputs magnetic data in **LSB**, with a conversion factor of **0.15 µT/LSB**.
263+
* Temperature readings are **relative only** (not absolute).
264+
* Calibration should be repeated if the sensor environment changes (metal nearby, relocation, etc.).
265+
* Tilt compensation requires an external **accelerometer** or IMU (e.g., LIS3DH, MPU6050, BNO055).
266+
267+
---
268+
269+
## 📚 References
62270

63-
## Datasheet
64-
For detailed information about the LIS2MDL sensor, refer to the [datasheet](https://www.st.com/resource/en/datasheet/lis2mdl.pdf).
271+
* [STMicroelectronics LIS2MDL Datasheet](https://www.st.com/resource/en/datasheet/lis2mdl.pdf)
272+
* [MicroPython Documentation](https://docs.micropython.org/en/latest/library/machine.I2C.html)
65273

66-
## Notes
67-
- The `heading_with_tilt_compensation` method has not been tested due to the lack of an accelerometer during development.
68-
- Ensure the I2C pins are correctly connected to the LIS2MDL module.
274+
---

lib/lis2mdl/exemple/magnet.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)