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 uorb interface. It supports the self-test capability
Application Programming Interface
#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:
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:
/* 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.
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.
/* 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.
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.
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.
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.
err = orb_ioctl(sensor, SNIOC_LPF, true);