stuck on "sending composition data get"

I'm working with nrf5340 for the BLE mesh Sensor example. It is divided into two parts one is the Sensor server and the other is the Client. I customize the code so it can read various sensors like TDS, turbidity etc. So after building both successfully, I'm facing an error in the provisioning part of the BLE mesh sensor server. The client part is easily provisioned in the right way but when I try to provision the server it gets stuck on "sending composition data get" if I exit the app and then try to get the composite data it again throws an error. both error are attached to the images. I'll also provide the code of BLE mesh sensor server. 

 

//model Handler 

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/drivers/sensor.h>
#include <bluetooth/mesh/models.h>
#include <bluetooth/mesh/sensor_types.h>
#include <dk_buttons_and_leds.h>
#include <float.h>
#include "model_handler.h"
#include <bluetooth/mesh/sensor.h>
#include <bluetooth/mesh/gen_battery.h>
#include <zephyr/drivers/adc.h>
#include <bluetooth/mesh/sensor_types.h>
#include <sys/types.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/toolchain.h>
#include <zephyr/fs/nvs.h>

#define STORAGE_ADDR 0x0000
#define POTENTIOMETER_CHANNEL 0 
#define TURBIDITY_CHANNEL 1 
#define FLASH_ERASE_BLOCK_SIZE 100
#define THRESHOLD_VALUE 500
#define TDS_CHANNEL 2 


#define POTENTIOMETER_SENSOR_TYPE_ID 0x0001
#define TURBIDITY_SENSOR_TYPE_ID 0x185E
#define TDS_SENSOR_TYPE_ID 0x2A6D

// Model IDs
#define POTENTIOMETER_MODEL_ID BT_MESH_MODEL_ID_SENSOR_SRV
#define TURBIDITY_MODEL_ID BT_MESH_MODEL_ID_SENSOR_SRV + 1
#define TDS_MODEL_ID BT_MESH_MODEL_ID_SENSOR_SRV + 2


int16_t sample_data[1];
int16_t turbidity_data[1];
int16_t tds_data[1];

const struct device *dev;

static int read_potentiometer_value(void)
{
    struct adc_sequence sequence = {
        .channels    = BIT(POTENTIOMETER_CHANNEL),
        .buffer      = sample_data,
        .buffer_size = sizeof(sample_data),
        .resolution  = 12, 
    };

    int ret = adc_read(dev, &sequence);
    if (ret < 0) {
        printk("Error reading ADC: %d\n", ret);
        return ret;
    }

    if (sample_data[0] <= THRESHOLD_VALUE) {
        return -EINVAL;
    }

    return sample_data[0];
}

static int read_turbidity_value(void)
{
    struct adc_sequence sequence = {
        .channels    = BIT(TURBIDITY_CHANNEL),
        .buffer      = turbidity_data,
        .buffer_size = sizeof(turbidity_data),
        .resolution  = 12, 
    };

    int ret = adc_read(dev, &sequence);
    if (ret < 0) {
        printk("Error reading ADC for turbidity: %d\n", ret);
        return ret;
    }

    return turbidity_data[0];
}


static int read_tds_value(void)
{
    struct adc_sequence sequence = {
        .channels    = BIT(TDS_CHANNEL),
        .buffer      = tds_data,
        .buffer_size = sizeof(tds_data),
        .resolution  = 12, 
    };

    int ret = adc_read(dev, &sequence);
    if (ret < 0) {
        printk("Error reading ADC for TDS: %d\n", ret);
        return ret;
    }

    return tds_data[0];
}


static struct nvs_fs fs = {
    .sector_size = FLASH_ERASE_BLOCK_SIZE,
    .sector_count = 8,
    .offset = STORAGE_ADDR,
};
static int save_to_nvs(int value)
{
    int ret;
    ret = nvs_write(&fs, STORAGE_ADDR, &value, sizeof(value));
    if (ret < 0) {
        printk("Failed to write to NVS: %d\n", ret);
        return ret;
    }
    return 0;
}

static int potentiometer_get_cb(const struct bt_mesh_sensor *sensor,
                                struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
{
    int pot_value = read_potentiometer_value();
    if (pot_value == -EINVAL) {
        return -EIO;
    } else if (pot_value < 0) {
        printk("Error reading potentiometer\n");
        return pot_value;
    }

    printk("Potentiometer Value: %d\n", pot_value); 

    save_to_nvs(pot_value);

    net_buf_simple_add_le16(buf, pot_value);

    return 0;
}

static int turbidity_get_cb(const struct bt_mesh_sensor *sensor,
                            struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
{
    int turbidity_value = read_turbidity_value();
    if (turbidity_value < 0) {
        printk("Error reading turbidity\n");
        return turbidity_value;
    }

    printk("Turbidity Value: %d\n", turbidity_value); 

    net_buf_simple_add_le16(buf, turbidity_value);

    return 0;
}


static int tds_get_cb(const struct bt_mesh_sensor *sensor,
                      struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
{
    int tds_value = read_tds_value();
    if (tds_value < 0) {
        printk("Error reading TDS\n");
        return tds_value;
    }

    printk("TDS Value: %d\n", tds_value); 

    net_buf_simple_add_le16(buf, tds_value);

    return 0;
}


// Define the potentiometer sensor with the callback
static const struct bt_mesh_sensor_type pot_sensor_type = {
    .id = POTENTIOMETER_SENSOR_TYPE_ID,
};

static struct bt_mesh_sensor pot_sensor = {
    .type = &pot_sensor_type, 
    .get = (int (*)(struct bt_mesh_sensor_srv *, struct bt_mesh_sensor *, struct bt_mesh_msg_ctx *, struct sensor_value *))potentiometer_get_cb,
};

// Define the turbidity sensor with the callback
static const struct bt_mesh_sensor_type turbidity_sensor_type = {
    .id = TURBIDITY_SENSOR_TYPE_ID,  // TODO: Change to appropriate ID for turbidity
};

static struct bt_mesh_sensor turbidity_sensor = {
    .type = &turbidity_sensor_type, 
    .get = (int (*)(struct bt_mesh_model *, struct bt_mesh_msg_ctx *, struct net_buf_simple *))turbidity_get_cb };


// Define the TDS sensor with the callback
static const struct bt_mesh_sensor_type tds_sensor_type = {
    .id = TDS_SENSOR_TYPE_ID,  // TODO: Change to appropriate ID for TDS
};

static const struct bt_mesh_model_op pot_sensor_srv_op[] = {
    { BT_MESH_SENSOR_OP_GET, 0, potentiometer_get_cb },
    BT_MESH_MODEL_OP_END,
};

static const struct bt_mesh_model_op turbidity_sensor_srv_op[] = {
    { BT_MESH_SENSOR_OP_GET, 0, turbidity_get_cb },
    BT_MESH_MODEL_OP_END,
};

static const struct bt_mesh_model_op tds_sensor_srv_op[] = {
    { BT_MESH_SENSOR_OP_GET, 0, tds_get_cb },
    BT_MESH_MODEL_OP_END,
};

static struct bt_mesh_sensor tds_sensor = {
    .type = &tds_sensor_type, 
    .get = tds_get_cb,
};

// Sensor model definition
static const struct bt_mesh_model_op _sensor_srv_op[] = {
    { BT_MESH_SENSOR_OP_GET, 0, potentiometer_get_cb },
    { BT_MESH_SENSOR_OP_GET, 0, turbidity_get_cb },
    BT_MESH_MODEL_OP_END,
};

struct bt_mesh_model_pub _sensor_pub;
BT_MESH_MODEL_PUB_DEFINE(sensor_pub, NULL, 2 + 2);

static struct bt_mesh_model models[] = {
    BT_MESH_MODEL(POTENTIOMETER_MODEL_ID, pot_sensor_srv_op, &_sensor_pub, &pot_sensor),
    BT_MESH_MODEL(TURBIDITY_MODEL_ID, turbidity_sensor_srv_op, &_sensor_pub, &turbidity_sensor),
    BT_MESH_MODEL(TDS_MODEL_ID, tds_sensor_srv_op, &_sensor_pub, &tds_sensor),
};

static struct bt_mesh_elem elements[] = {
    BT_MESH_ELEM(0, models, BT_MESH_MODEL_NONE), 
};

static const struct bt_mesh_comp comp = {
    .cid = 0x1234, 
    .pid = 0x0001, 
    .vid = 0x0100, 
    .elem = elements,
    .elem_count = ARRAY_SIZE(elements),
};

const struct bt_mesh_comp *model_handler_init(void)
{
    // Additional initialization if required...

    return &comp;
}
//main

#include <zephyr/bluetooth/bluetooth.h>
#include <bluetooth/mesh/models.h>
#include <bluetooth/mesh/dk_prov.h>
#include <dk_buttons_and_leds.h>
#include "model_handler.h"

#include <zephyr/drivers/adc.h>
#include <zephyr/drivers/gpio.h>

#define ADC_NODE DT_NODELABEL(adc)
static const struct device *const adc_dev = DEVICE_DT_GET(ADC_NODE);

#define ADC_RESOLUTION 10
#define ADC_OVERSAMPLING 4 /* 2^ADC_OVERSAMPLING samples are averaged */
#define ADC_MAX 4096
#define ADC_GAIN ADC_GAIN_1_5
#define ADC_REFERENCE ADC_REF_INTERNAL
#define ADC_REF_INTERNAL_MV 600UL
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)
#define ADC_CHANNEL_ID_POT 0
#define ADC_CHANNEL_ID_TURBIDITY 1
#define ADC_CHANNEL_ID_TDS 2
#define ADC_CHANNEL_INPUT_POT SAADC_CH_PSELP_PSELP_AnalogInput0
#define ADC_CHANNEL_INPUT_TURBIDITY SAADC_CH_PSELP_PSELP_AnalogInput1
#define ADC_CHANNEL_INPUT_TDS SAADC_CH_PSELP_PSELP_AnalogInput2

static const struct adc_channel_cfg pot_channel_cfg = {
    .gain = ADC_GAIN,
    .reference = ADC_REFERENCE,
    .acquisition_time = ADC_ACQUISITION_TIME,
    .channel_id = ADC_CHANNEL_ID_POT,
#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
    .input_positive = ADC_CHANNEL_INPUT_POT,
#endif
};

static const struct adc_channel_cfg turbidity_channel_cfg = {
    .gain = ADC_GAIN,
    .reference = ADC_REFERENCE,
    .acquisition_time = ADC_ACQUISITION_TIME,
    .channel_id = ADC_CHANNEL_ID_TURBIDITY,
#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
    .input_positive = ADC_CHANNEL_INPUT_TURBIDITY,
#endif
};

static const struct adc_channel_cfg tds_channel_cfg = {
    .gain = ADC_GAIN,
    .reference = ADC_REFERENCE,
    .acquisition_time = ADC_ACQUISITION_TIME,
    .channel_id = ADC_CHANNEL_ID_TDS,
#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
    .input_positive = ADC_CHANNEL_INPUT_TDS,
#endif
};

int16_t pot_sample_data[1];
int16_t turbidity_sample_data[1];
int16_t tds_sample_data[1];

struct adc_sequence pot_sequence = {
    .channels = BIT(ADC_CHANNEL_ID_POT),
    .buffer = pot_sample_data,
    .buffer_size = sizeof(pot_sample_data),
    .resolution = ADC_RESOLUTION
};

struct adc_sequence turbidity_sequence = {
    .channels = BIT(ADC_CHANNEL_ID_TURBIDITY),
    .buffer = turbidity_sample_data,
    .buffer_size = sizeof(turbidity_sample_data),
    .resolution = ADC_RESOLUTION
};

struct adc_sequence tds_sequence = {
    .channels = BIT(ADC_CHANNEL_ID_TDS),
    .buffer = tds_sample_data,
    .buffer_size = sizeof(tds_sample_data),
    .resolution = ADC_RESOLUTION
};

// Define the handle_adc_data function to handle the ADC data.
void handle_adc_data(int32_t adc_value, const char *sensor_name) {
    // You can add your code here to process the ADC data.
    // For example, you can send the data over Bluetooth Mesh or perform other actions.
    printk("Received %s ADC data: %d\n", sensor_name, adc_value);
}

static void bt_ready(int err)
{
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return;
    }

    printk("Bluetooth initialized\n");

    dk_leds_init();
    dk_buttons_init(NULL);

    err = bt_mesh_init(bt_mesh_dk_prov_init(), model_handler_init());
    if (err) {
        printk("Initializing mesh failed (err %d)\n", err);
        return;
    }

    if (IS_ENABLED(CONFIG_SETTINGS)) {
        settings_load();
    }

    /* This will be a no-op if settings_load() loaded provisioning info */
    bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);

    printk("Mesh initialized\n");
}

int main(void)
{
    int err;

    printk("Initializing...\n");

    err = bt_enable(bt_ready);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
    }

    while (1) {
        int err2;

        if (!device_is_ready(adc_dev)) {
            printk("adc_dev not ready\n");
            return -1;
        }

        // Setup and read potentiometer ADC value
        err2 = adc_channel_setup(adc_dev, &pot_channel_cfg);
        if (err2 != 0) {
            printk("Potentiometer ADC channel setup failed with error %d.\n", err2);
            return -1;
        }

        err2 = adc_read(adc_dev, &pot_sequence);
        if (err2 != 0) {
            printk("Potentiometer ADC reading failed with error %d\n", err2);
        }
        int32_t pot_value = pot_sample_data[0];
        handle_adc_data(pot_value, "Potentiometer");

        // Setup and read turbidity ADC value
        err2 = adc_channel_setup(adc_dev, &turbidity_channel_cfg);
        if (err2 != 0) {
            printk("Turbidity ADC channel setup failed with error %d.\n", err2);
            return -1;
        }

        err2 = adc_read(adc_dev, &turbidity_sequence);
        if (err2 != 0) {
            printk("Turbidity ADC reading failed with error %d\n", err2);
        }
        int32_t turbidity_value = turbidity_sample_data[0];
        handle_adc_data(turbidity_value, "Turbidity");

        // Setup and read TDS ADC value
        err2 = adc_channel_setup(adc_dev, &tds_channel_cfg);
        if (err2 != 0) {
            printk("TDS ADC channel setup failed with error %d.\n", err2);
            return -1;
        }

        err2 = adc_read(adc_dev, &tds_sequence);
        if (err2 != 0) {
            printk("TDS ADC reading failed with error %d\n", err2);
        }
        int32_t tds_value = tds_sample_data[0];
        handle_adc_data(tds_value, "TDS");

        k_msleep(5000);  // Sleep for 5 seconds before the next reading
    }

    return 0;
}

I think I messed up with GATT configuration,

Parents
  • Hello Omkar23,

    Have you looked at the log of the Sensor Server node to see if there are any clues there?

    If you are new to the nRF Connect SDK, but need to get some quick prototype running, then I recommend the approach where you start from a working sample, and slowly change things in cycles of small changes and tests.

    Hieu

  • Hello Hieu ,
    Thank you for your reply ,

    I see the logs but there is nothing that helps I'll share that too 

    It's been 2-3 months since I started working with NCS so I pretty much know about it. even though all things are going smoothly and out of nowhere it stopped provisioning. I also modified the Client code accordingly to my server code so its get compatible with the server but the client is running and provisioning in the right way. 

    Also sometimes I'm getting that INITIAL CONFIGURATION FAILED error i thought may be overall is the same error so i refer nrf-mesh-app-initial-configuration-failed but no luck

    I'm not getting any hint or idea what's went wrong here : \ 

Reply
  • Hello Hieu ,
    Thank you for your reply ,

    I see the logs but there is nothing that helps I'll share that too 

    It's been 2-3 months since I started working with NCS so I pretty much know about it. even though all things are going smoothly and out of nowhere it stopped provisioning. I also modified the Client code accordingly to my server code so its get compatible with the server but the client is running and provisioning in the right way. 

    Also sometimes I'm getting that INITIAL CONFIGURATION FAILED error i thought may be overall is the same error so i refer nrf-mesh-app-initial-configuration-failed but no luck

    I'm not getting any hint or idea what's went wrong here : \ 

Children
  • Hello Omkar,

    I will wait for the log then. It could be something very simple like a main stack overflow. I have met that in the past and fixed with CONFIG_MAIN_STACK_SIZE.

    I do agree that the log can sometimes be not very useful. However, in this situation, I think it's best to check what we have with it first and then improve the log as needed.

Related