sensors/lis2mdl: Create a UORB driver for the LIS2MDL magnetometer.

This commit is contained in:
Matteo Golin 2025-01-25 10:36:13 -05:00 committed by Xiang Xiao
parent 20f45f907f
commit 044879e7a3
10 changed files with 1664 additions and 1 deletions

View file

@ -30,3 +30,4 @@ general interafce.
sensors/mcp9600.rst
sensors/mpl115a.rst
sensors/sht4x.rst
sensors/lis2mdl.rst

View file

@ -0,0 +1,163 @@
=======
LIS2MDL
=======
Contributed by Matteo Golin.
The LIS2MDL is a low power, high-performance 3-axis magnetometer by ST
Microelectronics. It has I2C and SPI interfaces, although this driver currently
only supports I2C.
The driver uses the :doc:`uorb
</components/drivers/special/sensors/sensors_uorb>` interface. It supports the
self-test capability
Application Programming Interface
=================================
.. code-block:: c
#include <nuttx/sensors/lis2mdl.h>
The LIS2MDL registration function allows the driver to be registered as a UORB
driver. Registering this driver will cause the ``/dev/uorb/sensor_mag<n>`` topic
to appear, where ``n`` is the value of ``devno``.
The driver can be registered either in polling mode or in interrupt-driven mode.
The polling mode will create a kernel thread to poll the sensor periodically
according to the set interval. Polling mode is registered with ``NULL`` instead
of a real function pointer to the ``attach`` parameter, like so:
.. code-block:: c
int err;
/* Creates /dev/uorb/mag0 in polled mode */
err = lis2mdl_register(i2c_master, 0, 0x1e, NULL);
if (err < 0)
{
syslog(LOG_ERR, "Could not register LIS2MDL driver at 0x1E: %d\n", err);
}
To register in interrupt-driven mode, a function must be provided by the
calling code to register the LIS2MDL interrupt handler properly. This function
should take the interrupt handler and ``arg`` reference as arguments, and return
0 on success or a negated error code on failure. This function must also enable
the interrupt after it is registered successfully.
.. warning::
To use interrupt-driven mode, ``CONFIG_SCHED_HPWORK`` must be enabled.
The example below shows the example process for an RP2040 based board, but it
will be similar on other architectures:
.. code-block:: c
/* IRQ attach function example for RP2040 board */
static int board_lis2mdl_attach(xcpt_t handler, FAR void *arg)
{
int err;
err = rp2040_gpio_irq_attach(GPIO_MAG_INT, RP2040_GPIO_INTR_EDGE_HIGH,
handler, arg);
if (err < 0)
{
return err;
}
rp2040_gpio_enable_irq(GPIO_MAG_INT);
return err;
}
/* Later, in the board bringup code ... */
int err;
err = lis2mdl_register(i2c_master, 0, 0x1e, board_lis2mdl_attach);
if (err < 0)
{
syslog(LOG_ERR, "Couldn't register LIS2MDL driver: %d\n", err);
}
To debug this device, you can include the ``uorb_listener`` in your build with
debugging enabled. Running it will show the sensor measurements.
.. warning::
By default, when the sensor is deactivated via the UORB interface, it is put
into low power mode and set to idle. When it is reactivated, it is put in
high resolution mode and set to continuous measurement. If you want to
measure continuously in low power mode, you will need to use the
``SNIOC_SET_POWER_MODE`` command explained below.
The ``set_calibvalue`` interface to this sensor takes an array of three `float`
types, representing hard-iron offsets in micro Teslas. This offset is set on the
sensor and is subtracted from measurements to compensate for environmental
effects.
Some additional control commands for the LIS2MDL are listed below.
``SNIOC_WHO_AM_I``
------------------
This command reads the ``WHOAMI`` register of the LIS2MDL. This should always
return ``0x40``. The argument is a pointer to an 8-bit unsigned integer.
.. code-block:: c
uint8_t id; /* Should always contain 0x40 */
err = orb_ioctl(sensor, SNIOC_WHO_AM_I, &id);
``SNIOC_SET_POWER_MODE``
------------------------
This command selects the power mode of the LIS2MDL sensor. An argument of
``true`` puts the sensor in low power mode, and ``false`` puts the sensor into
high resolution mode.
.. code-block:: c
/* Puts LIS2MDL into low power mode */
err = orb_ioctl(sensor, SNIOC_WHO_AM_I, true);
``SNIOC_RESET``
----------------
Performs a soft reset of the LIS2MDL, which resets the user registers. This
command takes no arguments. Once this command is issue, 5 microseconds must pass
before the sensor is operational again.
.. code-block:: c
err = orb_ioctl(sensor, SNIOC_RESET, NULL);
``SNIOC_SENSOR_OFF``
--------------------
Performs a reboot of the LIS2MDL's memory contents. This command takes no
arguments. After the command is issued, 20ms must pass before the sensor is
operational again.
.. code-block:: c
err = orb_ioctl(sensor, SNIOC_SENSOR_OFF, NULL);
``SNIOC_SET_TEMP_OFFSET``
--------------------------
Enables or disables temperature compensation on the magnetometer. A arg of
``true`` enables compensation, ``false`` disables it. By default this is
enabled.
.. code-block:: c
err = orb_ioctl(sensor, SNIOC_SET_TEMP_OFFSET, true);
``SNIOC_LPF``
-------------
Enables or disables the magnetometer low pass filter. A arg of ``true`` enables
the filter, ``false`` disables it. By default this is disabled.
.. code-block:: c
err = orb_ioctl(sensor, SNIOC_LPF, true);

View file

@ -72,7 +72,6 @@ Drivers that are available also with the new sensor framework are marked with ``
- sgp30
- sht21
- sht3x
- :doc:`sht4x`
- sps30
- t67xx
- veml6070

View file

@ -484,8 +484,10 @@ Implemented Drivers
- goldfish_sensor
- hyt271
- l3gd20
- :doc:`lis2mdl`
- lsm9ds1
- ltr308
- mpu9250
- ms56xx
- :doc:`sht4x`
- wtgahrs2

View file

@ -248,6 +248,10 @@ if(CONFIG_SENSORS)
list(APPEND SRCS ltc4151.c)
endif()
if(CONFIG_SENSORS_LIS2MDL)
list(APPEND SRCS lis2mdl_uorb.c)
endif()
if(CONFIG_SENSORS_INA219)
list(APPEND SRCS ina219.c)
endif()

View file

@ -1436,6 +1436,34 @@ config SENSORS_MAX6675
---help---
Enables support for the MAX6675 driver
config SENSORS_LIS2MDL
bool "STMicro LIS2MDL 3-Axis magnetometer support"
default n
select I2C
---help---
Enable UORB driver support for the STMicro LIS2MDL 3-axis magnetometer.
if SENSORS_LIS2MDL
config SENSORS_LIS2MDL_FREQUENCY
int "LIS2MDL I2C frequency"
default 1000000
range 1 3400000
config SENSORS_LIS2MDL_THREAD_STACKSIZE
int "LIS2MDL worker thread stack size"
default 1024
---help---
The stack size for the worker thread that performs measurements
config SENSORS_LIS2MDL_FETCH
bool "Enable LIS2MDL fetch capability"
default n
---help---
Enables the `fetch` UORB function for the LIS2MDL
endif
config SENSORS_LIS3MDL
bool "STMicro LIS3MDL 3-Axis magnetometer support"
default n

View file

@ -208,6 +208,10 @@ ifeq ($(CONFIG_SENSORS_HTS221),y)
CSRCS += hts221.c
endif
ifeq ($(CONFIG_SENSORS_LIS2MDL),y)
CSRCS += lis2mdl_uorb.c
endif
ifeq ($(CONFIG_LM75_I2C),y)
CSRCS += lm75.c
endif

File diff suppressed because it is too large Load diff

View file

@ -473,6 +473,13 @@
#define SNIOC_SET_THERMO _SNIOC(0x009F)
/* Command: SNIOC_LPF
* Description: Enable the low pass filter
* Argument: Boolean true for enable, false to disable.
*/
#define SNIOC_LPF _SNIOC(0x00A0)
/****************************************************************************
* Public types
****************************************************************************/

View file

@ -0,0 +1,64 @@
/****************************************************************************
* include/nuttx/sensors/lis2mdl.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/sensors/ioctl.h>
#include <nuttx/irq.h>
/****************************************************************************
* Public Types
****************************************************************************/
struct i2c_master_s; /* Forward reference */
typedef int (*lis2mdl_attach)(xcpt_t, FAR void *arg);
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: lis2mdl_register
*
* Description:
* Register the LIS2MDL device as a UORB sensor.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with
* the LIS2MDL.
* addr - The I2C address of the LIS2MDL. Should always be 0x1e.
* devno - The device number to use for the topic (i.e. /dev/mag0)
* attach - A function which is called by this driver to attach the
* LIS2MDL interrupt handler to an IRQ. Pass NULL to operate
* in polling mode. This function should return 0 on succes
* and a negated error code otherwise.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int lis2mdl_register(FAR struct i2c_master_s *i2c, int devno, uint8_t addr,
lis2mdl_attach attach);