A lightweight C library for interfacing the STMicroelectronics LIS3MDL 3-axis magnetometer via I²C on the Raspberry Pi Pico (and other RP2040 boards) using the Pico C/C++ SDK.
- Features
- Hardware Requirements
- Software Requirements
- Getting Started
- Usage
- API
- Example
- License
- Contributing
- I²C read/write helpers with timeout
- Automatic register address auto-increment for multi-byte reads
- Initialization/configuration of all LIS3MDL control registers
- Hard-iron offset & threshold setup
- Raw & calibrated (µT) axis data
- Heading (°) calculation
- On-chip temperature reading (°C)
- Status & interrupt‐source register decoding
- Raspberry Pi Pico (or any RP2040 board)
- LIS3MDL magnetometer breakout or module
- Pull-up resistors on SDA/SCL if not provided on your breakout
- Raspberry Pi Pico SDK (tested on v1.5.0+)
- CMake 3.13+
- A GCC toolchain for ARM Cortex-M0+
-
Clone the Pico project (or add as a submodule):
git clone https://github.com/moeux/LIS3MDL.git cd LIS3MDL git submodule add https://github.com/moeux/LIS3MDL.git librares/LIS3MDL -
In your
CMakeLists.txt, add:add_subdirectory(libraries/LIS3MDL) target_link_libraries(<your_executable> PRIVATE LIS3MDL)
-
Build as usual
mkdir build cd build cmake .. make
| Pico Pin | LIS3MDL Pin |
|---|---|
| I2C0 SDA (GP4) | SDA |
| I2C1 SCL (GP5) | SCL |
| 3V3 | VCC |
| GND | GND |
#include "LIS3MDL.h" // Initialize I²C and LIS3MDL i2c_init(i2c0, 100 * 1000); gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); if (!lis3mdl_init()) { printf("LIS3MDL init failed!\n"); return; } // Optional: calibrate offsets (hard-iron) lis3mdl_set_offsets(0, 0, 0); // Optional: set interrupt threshold lis3mdl_set_threshold(1000);status_t st; axes_raw_data_t raw; axes_data_t data; int16_t temp_raw; // Poll for data-ready if (lis3mdl_read_status(&st) && st.data_available) { lis3mdl_read_raw_axes(&raw); data = lis3mdl_get_microteslas(raw, GAUSS_4); float heading = lis3mdl_get_heading(raw.x, raw.y); lis3mdl_read_raw_temperature(&temp_raw); float temperature = lis3mdl_get_celcius(temp_raw); printf("X: %.2f μT, Y: %.2f μT, Z: %.2f μT\n", data.x, data.y, data.z); printf("Heading: %.1f°\n", heading); printf("Temp: %.1f °C\n", temperature); }| Function | Description |
|---|---|
bool lis3mdl_init(void) | Initialize sensor & control registers |
bool lis3mdl_set_offsets(int16_t x,y,z) | Write hard-iron offsets |
bool lis3mdl_set_threshold(uint16_t th) | Set interrupt threshold |
bool lis3mdl_read_status(status_t *st) | Read status register flags |
bool lis3mdl_read_interrupt_source(int_src_t *src) | Read interrupt source register |
bool lis3mdl_read_raw_axes(axes_raw_data_t *d) | Read & auto-center raw axis data |
axes_data_t lis3mdl_get_microteslas(...) | Convert raw data to microteslas based on chosen gauss scale |
float lis3mdl_get_heading(int16_t x,int16_t y) | Compute 2D compass heading (°) |
bool lis3mdl_read_raw_temperature(int16_t *t) | Read raw temperature |
float lis3mdl_get_celcius(int16_t t) | Convert raw temp to Celsius |
(See header comments for full prototypes.)
See the main() in LIS3MDL.c for a complete demo:
- Turns the on-board LED on while initializing
- Prints raw & scaled axes, heading, and temperature every sample
This project is licensed under the MIT License. See LICENSE for details.
- Fork the repo
- Create a feature branch (
git checkout -b feature/awesome) - Commit your changes
- Open a Pull Request