BMM150 on Thingy:53

I am trying to build a firmware for Thingy:53 that simply streams the magnetometer via BLE. I have BLE and Gatt working fine; I can even read and stream the IMU sensor. But all of my attempts at magnetometer has failed. When I call is_device_ready, I always get False not matter what I do. The entry point to the code is "mag_init". Please help me resolve the issue.

proj.conf

CONFIG_SENSOR=y
CONFIG_I2C=y
CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_LED=y
CONFIG_LED_PWM=y
CONFIG_PWM=y
CONFIG_BMI270=y
CONFIG_BMM150=y
CONFIG_ADXL362=y
CONFIG_BMM150_SAMPLING_RATE_RUNTIME=y
CONFIG_BMM150_SAMPLING_REP_XY=y
CONFIG_BMM150_SAMPLING_REP_Z=y
CONFIG_BMM150_PRESET_REGULAR=y
CONFIG_BMM150_PRESET_HIGH_ACCURACY=y
 
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED=y
overlay
&spi3{
  status = "okay";
  bmi270: spi-dev-bmi270@1 {
    status = "okay";
  };
  adxl362: spi-dev-adxl362@0 {
    status = "okay";
  };
};

&i2c1 {
  status = "okay";
  bmm150@10 {
    compatible = "bosch,bmm150";
    reg = <0x10>;
    status = "okay";
    vin-supply = <&sensor_pwr_ctrl>;
  };
};

&sensor_pwr_ctrl {
  regulator-boot-on;
  startup-delay-us = <1000>;
status = "okay";
};
mag_utils.h
#pragma once
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/util.h>
#include <stdint.h>

struct mag_sample_uT {
int32_t x_uT;
int32_t y_uT;
int32_t z_uT;
int64_t ts_ns; /* monotonic time */
};

int mag_init(void);
int mag_utils_get_latest(struct mag_sample_uT *out);
mag_utils.c
#include "mag/mag_utils.h"
#include <zephyr/drivers/sensor.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mag_utils, LOG_LEVEL_INF);

/* Get the single on-board BMM150 by compatible */
static const struct device *const mag_dev = DEVICE_DT_GET_ONE(bosch_bmm150);
static struct mag_sample_uT latest;
static struct k_mutex latest_lock;
static struct k_timer poll_timer;
static struct k_work poll_work;

static inline int64_t now_ns(void)
{
/* Convert uptime ticks to ns (monotonic). */
return k_ticks_to_ns_floor64(k_uptime_ticks());
}

static void poll_fn(struct k_work *work)
{
ARG_UNUSED(work);
if (!device_is_ready(mag_dev)) {
LOG_ERR("BMM150 device not ready");
return;
}

if (sensor_sample_fetch(mag_dev) < 0) {
LOG_WRN("BMM150 fetch failed");
return;
}

struct sensor_value v[3];
if (sensor_channel_get(mag_dev, SENSOR_CHAN_MAGN_XYZ, v) < 0) {
LOG_WRN("BMM150 get XYZ failed");
return;
}

struct mag_sample_uT s = {
.x_uT = (int32_t)sensor_value_to_double(&v[0]) * 1000000.0,
.y_uT = (int32_t)sensor_value_to_double(&v[1]) * 1000000.0,
.z_uT = (int32_t)sensor_value_to_double(&v[2]) * 1000000.0,
.ts_ns = now_ns(),
};

k_mutex_lock(&latest_lock, K_FOREVER);
latest = s;
k_mutex_unlock(&latest_lock);
}

static void timer_fn(struct k_timer *t)
{
ARG_UNUSED(t);
k_work_submit(&poll_work);
}

int mag_init(void)
{
for (int i = 0; i < 20; ++i) {
if (device_is_ready(mag_dev)) {
break;
}
k_msleep(100);
}

if (!device_is_ready(mag_dev)) {
LOG_ERR("BMM150 %s not ready", mag_dev ? mag_dev->name : "(null)");
return -ENODEV;
}

/* Try to request ~10 Hz sampling in the sensor if supported.
* If the driver ignores it, we still poll at 10 Hz below.
*/
#ifdef SENSOR_ATTR_SAMPLING_FREQUENCY
struct sensor_value rate = {.val1 = 10, .val2 = 0};
(void)sensor_attr_set(mag_dev, SENSOR_CHAN_ALL,
SENSOR_ATTR_SAMPLING_FREQUENCY, &rate);
#endif

k_mutex_init(&latest_lock);
k_work_init(&poll_work, poll_fn);
k_timer_init(&poll_timer, timer_fn, NULL);
k_timer_start(&poll_timer, K_NO_WAIT, K_MSEC(100)); /* 10 Hz */

LOG_INF("Magnetometer initialized (BMM150)");
return 0;
}

int mag_utils_get_latest(struct mag_sample_uT *out)
{
if (!out) return -EINVAL;
k_mutex_lock(&latest_lock, K_FOREVER);
*out = latest;
k_mutex_unlock(&latest_lock);
return 0;
}
Related