cancel
Showing results for 
Search instead for 
Did you mean: 

Receiving a NMAK when reading out WhoAmI register - lsm6dsox

ReginaA101
Associate

Hi everyone,

I am currently trying to get a lsm6dsox to interface with a Nordic nRF52833 board using i2c communication. I am looking to read accelerometer/gyro values.

I am able to write to the sensor but I am unable to read from the sensor without receiving a NMAK. 

I am using the STEVAL-MKI217V1 adapter board to connect to my nRF52833.

I have connected the VDD/VDDIO pins to VCC, my SCL/SDA pins to the pins I configured for i2c communication, I have connected CS to VDD, GND pins to GND, and SDO to ground. 

This is my result from the Logic analyzer

 
Screenshot 2025-02-28 175333.png

This is my source code:

Main.c:

/*
 * Copyright (c) 2020 Yestin Sun
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>

static inline float out_ev(struct sensor_value *val)
{
    return (val->val1 + (float)val->val2 / 1000000);
}

static void fetch_and_display(const struct device *dev)
{
    struct sensor_value x, y, z;
    static int trig_cnt;

    trig_cnt++;

    /* lsm6dso accel */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_ACCEL_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, &x);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Y, &y);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &z);

    printf("accel x:%f ms/2 y:%f ms/2 z:%f ms/2\n",
            (double)out_ev(&x), (double)out_ev(&y), (double)out_ev(&z));

    /* lsm6dso gyro */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_X, &x);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_Y, &y);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &z);

    printf("gyro x:%f rad/s y:%f rad/s z:%f rad/s\n",
            (double)out_ev(&x), (double)out_ev(&y), (double)out_ev(&z));

    printf("trig_cnt:%d\n\n", trig_cnt);
}

static int set_sampling_freq(const struct device *dev)
{
    int ret = 0;
    struct sensor_value odr_attr;

    /* set accel/gyro sampling frequency to 12.5 Hz */
    odr_attr.val1 = 12.5;
    odr_attr.val2 = 0;

    ret = sensor_attr_set(dev, SENSOR_CHAN_ACCEL_XYZ,
            SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr);
    if (ret != 0) {
        printf("Cannot set sampling frequency for accelerometer.\n");
        return ret;
    }

    ret = sensor_attr_set(dev, SENSOR_CHAN_GYRO_XYZ,
            SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr);
    if (ret != 0) {
        printf("Cannot set sampling frequency for gyro.\n");
        return ret;
    }

    return 0;
}

#ifdef CONFIG_LSM6DSO_TRIGGER
static void trigger_handler(const struct device *dev,
                const struct sensor_trigger *trig)
{
    fetch_and_display(dev);
}

static void test_trigger_mode(const struct device *dev)
{
    struct sensor_trigger trig;

    if (set_sampling_freq(dev) != 0)
        return;

    trig.type = SENSOR_TRIG_DATA_READY;
    trig.chan = SENSOR_CHAN_ACCEL_XYZ;

    if (sensor_trigger_set(dev, &trig, trigger_handler) != 0) {
        printf("Could not set sensor type and channel\n");
        return;
    }
}

#else
static void test_polling_mode(const struct device *dev)
{
    if (set_sampling_freq(dev) != 0) {
        return;
    }

    while (1) {
        fetch_and_display(dev);
        k_sleep(K_MSEC(1000));
    }
}
#endif

int main(void)
{
    const struct device *const dev = DEVICE_DT_GET_ONE(st_lsm6dso);

    if (!device_is_ready(dev)) {
        printk("%s: device not ready.\n", dev->name);
        return 0;
    }

#ifdef CONFIG_LSM6DSO_TRIGGER
    printf("Testing LSM6DSO sensor in trigger mode.\n\n");
    test_trigger_mode(dev);
#else
    printf("Testing LSM6DSO sensor in polling mode.\n\n");
    test_polling_mode(dev);
#endif
    return 0;
}
 
Overlay file:
#include <zephyr/dt-bindings/sensor/lsm6dso.h>
&i2c0 {
    status = "okay";
    compatible = "nordic,nrf-twim";
    pinctrl-0 = <&i2c0_default>;
    pinctrl-1 = <&i2c0_sleep>;
    pinctrl-names = "default", "sleep";
    lsm6dsox:lsm6dsox@6A {
        compatible = "st,lsm6dso";
        status = "ok";
        label = "LSM6DSO";
        reg = <0x6A>;
        accel-odr = <LSM6DSO_DT_ODR_1Hz6>;
    };
};
&pinctrl {
    i2c0_default: i2c0_default {
        group1  {
            psels = <NRF_PSEL(TWIM_SCL, 0, 27)>, <NRF_PSEL(TWIM_SDA, 0, 26)>;
            bias-pull-up;
        };
    };

    i2c0_sleep: i2c0_sleep {
        group1  {
            psels = <NRF_PSEL(TWIM_SCL, 0, 27)>,
                    <NRF_PSEL(TWIM_SDA, 0, 26)>;
            low-power-enable;
        };
    };
};
 
Is there something I am missing to ensure that I can read via i2c?
I appreciate anyone's help as I am very stuck on this.
Thanks,
Regina
1 REPLY 1
Federica Bossi
ST Employee

Hi @ReginaA101 ,

As written in LSM6DSOX DS, in the description of I2C communication, for READs transactions, the last ACK is a NotMasterACK.

FedericaBossi_0-1741364290147.jpeg

I think that the protocol communication analyzer is not able to discriminate between slave and master ACKs.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.