Bluetooth connexion issue

Hello community, 
I'm trying to implement BT service on my project to be able to connect with my phone 
for information my project displays data from sensors(BME280, INA219, MPU6050)  connected to my D-kit 
i'm using nrf connect V1.8.0 and NRF5340dk
i got inspired from this BT tutorial to create my services 
but in terms of BT connexion i don't get the device on my ophone when i scan devices around 
which means that connexion isn't established
and i got this message "Advertising failed to start (err-11)"
i will attach below my output display 

i tried to flash my D-kit directly but it didn't work 
and i tried to activate the BT but in vain too 
i tried to use this function

    //Start advertising
	err = bt_le_adv_start(BT_LE_ADV_PARAM(
							BT_LE_ADV_OPT_CONNECTABLE
							|BT_LE_ADV_OPT_ONE_TIME
							|BT_LE_ADV_OPT_USE_NAME,
							160, 	// units of 0.625ms
							1600),	// units of 0.625ms
						ad, ARRAY_SIZE(ad),
						sd, ARRAY_SIZE(sd));

Can you guys help  by telling me what's wrong on this situation 
why can't i get the bt to advertise 
do i missing something on the main or on the activation 
by the way my prj.conf should be good and i will liked below
 
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_MAX_CONN=1
CONFIG_BT_L2CAP_TX_BUF_COUNT=5
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="My_Device"
CONFIG_BT_DEVICE_APPEARANCE=962

CONFIG_HEAP_MEM_POOL_SIZE=2048

# This example requires more workqueue stack
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

CONFIG_STDOUT_CONSOLE=y
CONFIG_CBPRINTF_FP_SUPPORT=y
CONFIG_SENSOR=y
CONFIG_I2C=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_UART_CONSOLE=n
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_PRINTK=y
CONFIG_INA219=y
CONFIG_BME280=y

CONFIG_SHELL_BACKEND_SERIAL=y


Can you help me with this please 
i will be very grateful 

Parents
  • Hi,

    There are a few things missing here, most can be ignored, but for instance my_service_send() and my_service_init() are used by not defined anywhere in this code. So I ignore that.

    There are quite a few other things to note though, and that makes me want to stress that you should ensure that your code builds without warnings. The warnings are there to help you. For instance, in bt_ready_data_data_data_data_work_work_work_work_fn() you have an err variable that is not initialized (so the content is meaningless), and you use that to figure out if BT initialization was successful or not. Which is clearly pointless. For this err to be meaningful, change the function to use int err as parameter, and remove the err variable you declare within (refer to for instance the beacon example in the SDK to see how it is done).

    When I remove most of your code which is not related to BT and do a quick clean-up, advertising starts without an error.

    Here is your stripped main.c file that works fine BT vise (advertising works and I am able to connect):

    #include <zephyr.h>
    #include <device.h>
    #include <stdio.h>
    #include <sys/util.h>
    #include <sys/printk.h>
    #include <inttypes.h>
    #include <drivers/gpio.h>
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/byteorder.h>
    #include <soc.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/hci.h>
    #include <bluetooth/conn.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    
    
    #define DEVICE_NAME 		CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN 		(sizeof(DEVICE_NAME) - 1)
    
    #define SLEEP_TIME_MS	1
    
    /*
     * Get button configuration from the devicetree sw0 alias. This is mandatory.
     Replace DT_ALIAS(sw0) by sw27 to get output through SCT click
     */
    
    
    			 
    
    #define MY_SERVICE_UUID 0x0001
    
    
    static K_SEM_DEFINE(ble_init_ok, 0, 1);
    
    static const struct bt_data ad[] = 
    {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = 
    {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, MY_SERVICE_UUID),
    };
    struct bt_conn *my_connection;
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	my_connection = conn;
    
    	if (err) 
    	{
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    	else if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection established!		\n\
    		Connected to: %s					\n\
    		Role: %u							\n\
    		Connection interval: %u				\n\
    		Slave latency: %u					\n\
    		Connection supervisory timeout: %u	\n"
    		, addr, info.role, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    }
    
    static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
    {
    	//If acceptable params, return true, otherwise return false.
    	return true; 
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, uint16_t timeout)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    	
    	if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection parameters updated!	\n\
    		Connected to: %s						\n\
    		New Connection Interval: %u				\n\
    		New Slave Latency: %u					\n\
    		New Connection Supervisory Timeout: %u	\n"
    		, addr, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static struct bt_conn_cb conn_callbacks = 
    {
    	.connected			= connected,
    	.disconnected   		= disconnected,
    	.le_param_req			= le_param_req,
    	.le_param_updated		= le_param_updated
    };
    
    
    
    
    
    static void error(void)
    {
    	while (true) {
    		printk("Error!\n");
    		/* Spin for ever */
    		k_sleep(K_MSEC(1000)); //1000ms
    	}
    }
    
    
    
    static void bt_ready_data_data_data_data_work_work_work_work_fn(int err)
    {
    	if (err) 
    	{
    		printk("BLE init failed with error code %d\n", err);
    		return;
    	}
    
    	//Configure connection callbacks
    	bt_conn_cb_register(&conn_callbacks);
    
    	//Initalize services
    	//err = my_service_init();
            //printk("Bluetooth initialized \n");
    
    	if (err) 
    	{
    		printk("Failed to init LBS (err:%d)\n", err);
    		return;
    	}
            
    
    	//Start advertising
    	err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
    	if (err) 
    	{
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Advertising successfully started\n");
    
    	k_sem_give(&ble_init_ok);
    }
    
    
    void main(void)
    { 
        int err = 0;
    	uint32_t number = 0;
    
    
    	printk("Press the button\n");
    	/*if (led.port) {
    		while (1) {
    			// If we have an LED, match its state to the button's. 
    			int val = gpio_pin_get_dt(&button);
                            
    			if (val >= 0) {
    				gpio_pin_set_dt(&led, val);
    			}
    			k_msleep(SLEEP_TIME_MS);
    		}
    	}*/
            printk("Starting BLE Service\n");
    	
    	err = bt_enable(bt_ready_data_data_data_data_work_work_work_work_fn);
    
    	if (err) 
    	{
    		printk("BLE initialization failed (err %d)\n", err);
    		error(); //Catch error
    	}
    	
    	/* 	Bluetooth stack should be ready in less than 100 msec. 								\
    																							\
    		We use this semaphore to wait for bt_enable to call bt_ready before we proceed 		\
    		to the main loop. By using the semaphore to block execution we allow the RTOS to 	\
    		execute other tasks while we wait. */	
    	err = k_sem_take(&ble_init_ok, K_MSEC(500));
            
    	if (!err) 
    	{
    		printk("Bluetooth initialized\n");
    	} else 
    	{
    		printk("BLE initialization did not complete in time\n");
    		error(); //Catch error
    	}
    
    	for (;;) 
    	{
    		// Main loop
    		//my_service_send(my_connection, (uint8_t *)&number, sizeof(number));
    		number++;
    		k_sleep(K_MSEC(1000)); // 1000ms
    	}
    
    }
    

  • Hello, 
    infinite thanks for taking a look into my warnings 
    but i want to tell you that: 
    now that i replaced "static void bt_ready_data_data_data_data_work_work_work_work_fn(struct k_work *work)" with "static void bt_ready_data_data_data_data_work_work_work_work_fn(int err)"
    i'm getting a new code error 

    and since u told me that i should pay attention to warnings 
    after my build i'm getting a warning when i'm calling the "k_work_init(&bt_ready_data_data_data_data_work, bt_ready_data_data_data_data_work_work_work_work_fn);" in my static void work init 

    the warning message is " passing argument 2 of 'k_work_init' from incompatible pointer type [-Wincompatible-pointer-types] "
    Do you know what the code error means please
    is it caused by the warning ? how can i repare this warning please ?
    grateful for your help in advance

  • Rihab said:
    i tried to search for the function bt_le_is_ready but i can't find it no where 

    There is no need for it here, it was just an idea based on the error you described before I saw all your code.

    Rihab said:
    and since u told me that i should pay attention to warnings 

    Yes, that is good.

    Rihab said:
    the warning message is " passing argument 2 of 'k_work_init' from incompatible pointer type [-Wincompatible-pointer-types] "
    Do you know what the code error means please
    is it caused by the warning ? how can i repare this warning please ?

    Why are there 2 arguments?  The first argument you had there was invalid,  bt_ready_data_data_data_data_work_work_work_work_fn must have the prototype defined by the BT application, so it can only take an integer as argument, and this will be the error code. You cannot have struct k_work in there, as this is populated by the Bluetooth stack and it would not know where to put there. So, your bt_ready_data_data_data_data_work_work_work_work_fn must look like this (though you can of course change the name of the function and the name of the variable holding the error code if you like):

    static void bt_ready_data_data_data_data_work_work_work_work_fn(int err)
  • Thank you so much for the explanation. Now i entirely understand.
    But in your opinion what is causing the BT initialization to fail ?
    do you know what the code error below refers to please  ? 

    BLE init failed with error code 536875240


  • I have not seen your updated code, but based on what you described I assume the problem is related to what I described in my previous post: Your error variable is invalid and contains random/rubbish data, and you print that. So it does not mean anything.

  • here's my updated code 

    #include <zephyr.h>
    #include <device.h>
    #include <drivers/sensor.h>
    #include <stdio.h>
    #include <sys/util.h>
    #include <sys/printk.h>
    #include <inttypes.h>
    #include <drivers/gpio.h>
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/byteorder.h>
    #include <soc.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/hci.h>
    #include <bluetooth/conn.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    
    #include "C:/sdk/v1.9.0/zephyr/samples/sensor/inaa219/services/my_service.h"
    
    #define DEVICE_NAME 		CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN 		(sizeof(DEVICE_NAME) - 1)
    
    #define SLEEP_TIME_MS	1
    
    /*
     * Get button configuration from the devicetree sw0 alias. This is mandatory.
     Replace DT_ALIAS(sw0) by sw27 to get output through SCT click
     */
    #define MY_SERVICE_UUID 0x0001
    #define SW0_NODE	DT_ALIAS(sw0)
    #if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
    #error "Unsupported board: sw0 devicetree alias is not defined"
    #endif
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,
    							      {0});
    static struct gpio_callback button_cb_data;
    static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
    						     {0});
    static int on_click = 1;
    
    #define APP_WORK_QUEUE_SIZE 4096	
    #define APP_WORK_QUEUE_PRI -1
    
    K_THREAD_STACK_DEFINE(application_stack_area, APP_WORK_QUEUE_SIZE);	
    			 
    static struct k_work_q application_work_q;
    static struct k_work bt_ready_data_data_data_data_work;
    static struct k_work get_ina219_data_data_data_work;
    //static struct k_work get_bme280_data_data_work;
    static struct k_work get_mpu6050_data_work;	
    
    static K_SEM_DEFINE(ble_init_ok, 0, 1);
    
    static const struct bt_data ad[] = 
    {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = 
    {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, MY_SERVICE_UUID),
    };
    struct bt_conn *my_connection;
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	my_connection = conn;
    
    	if (err) 
    	{
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    	else if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection established!		\n\
    		Connected to: %s			\n\
    		Role: %u				\n\
    		Connection interval: %u			\n\
    		Slave latency: %u                       \n\
    		Connection supervisory timeout: %u	\n"
    		, addr, info.role, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    }
    
    static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
    {
    	//If acceptable params, return true, otherwise return false.
    	return true; 
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, uint16_t timeout)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    	
    	if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection parameters updated!	\n\
    		Connected to: %s			\n\
    		New Connection Interval: %u		\n\
    		New Slave Latency: %u			\n\
    		New Connection Supervisory Timeout: %u	\n"
    		, addr, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static struct bt_conn_cb conn_callbacks = 
    {
    	.connected			= connected,
    	.disconnected   		= disconnected,
    	.le_param_req			= le_param_req,
    	.le_param_updated		= le_param_updated
    };
    
    static const char *now_str(void)
    {
    	static char buf[16]; /* ...HH:MM:SS.MMM */
    	uint32_t now = k_uptime_get_32();
    	unsigned int ms = now % MSEC_PER_SEC;
    	unsigned int s;
    	unsigned int min;
    	unsigned int h;
    
    	now /= MSEC_PER_SEC;
    	s = now % 60U;
    	now /= 60U;
    	min = now % 60U;
    	now /= 60U;
    	h = now;
    
    	snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
    		 h, min, s, ms);
    	return buf;
    }
    
    static int process_mpu6050(const struct device *dev)
    {
    	struct sensor_value temperature;
    	struct sensor_value accel[3];
    	struct sensor_value gyro[3];
    	int rc = sensor_sample_fetch(dev);
    
    	if (rc == 0) {
    		rc = sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ,
    					accel);
    	}
    	if (rc == 0) {
    		rc = sensor_channel_get(dev, SENSOR_CHAN_GYRO_XYZ,
    					gyro);
    	}
    	if (rc == 0) {
    		rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP,
    					&temperature);
    	}
    	if (rc == 0) {
    		printf("[%s]:%g Cel\n"
    		       "  accel %f %f %f m/s/s\n"
    		       "  gyro  %f %f %f rad/s\n",
    		       now_str(),
    		       sensor_value_to_double(&temperature),
    		       sensor_value_to_double(&accel[0]),
    		       sensor_value_to_double(&accel[1]),
    		       sensor_value_to_double(&accel[2]),
    		       sensor_value_to_double(&gyro[0]),
    		       sensor_value_to_double(&gyro[1]),
    		       sensor_value_to_double(&gyro[2]));
    	} else {
    		printf("sample fetch/get failed: %d\n", rc);
    	}
    
    	return rc;
    }
    
    #ifdef CONFIG_MPU6050_TRIGGER
    static struct sensor_trigger trigger;
    
    static void handle_mpu6050_drdy(const struct device *dev,
    				struct sensor_trigger *trig)
    {
    	int rc = process_mpu6050(dev);
    
    	if (rc != 0) {
    		printf("cancelling trigger due to failure: %d\n", rc);
    		(void)sensor_trigger_set(dev, trig, NULL);
    		return;
    	}
    }
    #endif /* CONFIG_MPU6050_TRIGGER */
    
    static const struct device *get_ina219_device(void)
    {
      const struct device *dev = DEVICE_DT_GET_ANY(ti_ina219);
            if(dev == NULL){
                      printk("\nEror: no device found. \n");
                      return NULL;
             }
             if (!device_is_ready(dev)) {
    		printk("\nError: Device \"%s\" is not ready; "
    		       "check the driver initialization logs for errors.\n",
    		       dev->name);
    		return NULL;
    	}
    
    	//printk("Found device \"%s\", getting sensor data\n", dev->name);
    	return dev;
    }
    
    /*static const struct device *get_bme280_device(void)
    {
    	const struct device *dev = DEVICE_DT_GET_ANY(bosch_bme280);
    
    	if (dev == NULL) {
    		// No such node, or the node does not have status "okay". 
    		printk("\nError: no device found.\n");
    		return NULL;
    	}
    
    	if (!device_is_ready(dev)) {
    		printk("\nError: Device \"%s\" is not ready; "
    		       "check the driver initialization logs for errors.\n",
    		       dev->name);
    		return NULL;
    	}
    
    	//printk("Found device \"%s\", getting sensor data\n", dev->name);
    	return dev;
    }*/
    
    static void get_mpu6050_data_work_fn(struct k_work *work)
    {
            
    	printk("-----------------Get MPU6050 data\n" );
    
            struct sensor_value temperature;
            struct sensor_value accel[3];
            struct sensor_value gyro[3];
    
            printf("[%s]:%g Cel\n"
    	"  accel %f %f %f m/s/s\n"
    	"  gyro  %f %f %f rad/s\n",
    	now_str(),
    	sensor_value_to_double(&temperature),
    	sensor_value_to_double(&accel[0]),
    	sensor_value_to_double(&accel[1]),
    	sensor_value_to_double(&accel[2]),
    	sensor_value_to_double(&gyro[0]),
    	sensor_value_to_double(&gyro[1]),
    	sensor_value_to_double(&gyro[2]));
    	
    }
    
    /*static void get_bme280_data_data_work_work_fn(struct k_work *work)
    {
                    printk("+++++++++++++++++Get BME280 data\n");
                    
    		struct sensor_value temp, press, humidity;
    		sensor_sample_fetch(get_bme280_device());
    		sensor_channel_get(get_bme280_device(), SENSOR_CHAN_AMBIENT_TEMP, &temp);
    		sensor_channel_get(get_bme280_device(), SENSOR_CHAN_PRESS, &press);
    		sensor_channel_get(get_bme280_device(), SENSOR_CHAN_HUMIDITY, &humidity);
    
    		printk("temp: %d.%06d; press: %d.%06d; humidity: %d.%06d\n",
    		      temp.val1, temp.val2, press.val1, press.val2,
    		      humidity.val1, humidity.val2);
    	
    }*/
    
    static void get_ina219_data_data_data_work_work_work_fn(struct k_work *work)
    {
          printk("################Get INA219 data\n");
    
          struct sensor_value v_bus, power, current;
          sensor_sample_fetch(get_ina219_device());
                    sensor_channel_get(get_ina219_device(), SENSOR_CHAN_VOLTAGE, &v_bus);
    		sensor_channel_get(get_ina219_device(), SENSOR_CHAN_POWER, &power);
    		sensor_channel_get(get_ina219_device(), SENSOR_CHAN_CURRENT, &current);
          
    		printf("Bus: %f [V] -- "
    			"Power: %f [W] -- "
    			"Current: %f [A]\n",
    		       sensor_value_to_double(&v_bus),
    		       sensor_value_to_double(&power),
    		       sensor_value_to_double(&current));
    }
    
    static void error(void)
    {
    	while (true) {
    		printk("Error!\n");
    		/* Spin for ever */
    		k_sleep(K_MSEC(1000)); //1000ms
    	}
    }
    
    void button_pressed(const struct device *dev, struct gpio_callback *cb,
    		    uint32_t pins)
    {
            printk("***************Button pressed at ");
            int val = gpio_pin_get_dt(&button);
            if(val == 1){
            gpio_pin_set_dt(&button, val);
            printk("Number of cycle : %d\n", on_click++);
            }
            else if (val == 0){
            printk("Number of cycle : %d\n", on_click);
            }
    	k_work_submit_to_queue(&application_work_q, &get_mpu6050_data_work);
            //k_work_submit_to_queue(&application_work_q, &get_bme280_data_data_work);
            k_work_submit_to_queue(&application_work_q, &get_ina219_data_data_data_work);
            k_work_submit_to_queue(&application_work_q, &bt_ready_data_data_data_data_work);
            
    }
    static void bt_ready_data_data_data_data_work_work_work_work_fn(int err)
    {
    	if (err) 
    	{
    		printk("BLE init failed with error code %d\n", err);
    		return;
    	}
    	//Configure connection callbacks
            printk("callbacks");
    	bt_conn_cb_register(&conn_callbacks);
    	//Initalize services
            printk("initialisation");
    	err = my_service_init();
            printk("LBS \n");
           
    	//Start advertising
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
            printk("BT Starting \n");  
    	if (err) 
    	{
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
            else{
    	printk("Advertising successfully started\n");
            }
    	k_sem_give(&ble_init_ok);
    }
    
    static void work_init(void)
    {
    	k_work_init(&get_mpu6050_data_work, get_mpu6050_data_work_fn);
    	//k_work_init(&get_bme280_data_data_work, get_bme280_data_data_work_work_fn);
            k_work_init(&get_ina219_data_data_data_work, get_ina219_data_data_data_work_work_work_fn);
            k_work_init(&bt_ready_data_data_data_data_work, bt_ready_data_data_data_data_work_work_work_work_fn);
    }
    
    void main(void)
    {
    	int ret;       
            int err = 0;
    	uint32_t number = 0;
    
    	k_work_queue_start(&application_work_q, application_stack_area,
    			K_THREAD_STACK_SIZEOF(application_stack_area),
    			APP_WORK_QUEUE_PRI, NULL);
    	work_init();
    
    	if (!device_is_ready(button.port)) {
    		printk("Error: button device %s is not ready\n",
    		       button.port->name);
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
    	if (ret != 0) {
    		printk("Error %d: failed to configure %s pin %d\n",
    		       ret, button.port->name, button.pin);
    		return;
    	}
    
    	ret = gpio_pin_interrupt_configure_dt(&button,
    					      GPIO_INT_EDGE_TO_ACTIVE);
    	if (ret != 0) {
    		printk("Error %d: failed to configure interrupt on %s pin %d\n",
    			ret, button.port->name, button.pin);
    		return;
    	}
    
    	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
    	gpio_add_callback(button.port, &button_cb_data);
    	printk("Set up button at %s pin %d\n", button.port->name, button.pin);
    
    	if (led.port && !device_is_ready(led.port)) {
    		printk("Error %d: LED device %s is not ready; ignoring it\n",
    		       ret, led.port->name);
    		led.port = NULL;
    	}
    	if (led.port) {
    		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
    		if (ret != 0) {
    			printk("Error %d: failed to configure LED device %s pin %d\n",
    			       ret, led.port->name, led.pin);
    			led.port = NULL;
    		} else {
    			printk("Set up LED at %s pin %d\n", led.port->name, led.pin);
    		}
    	}
    
    	printk("Press the button\n");
    	/*if (led.port) {
    		while (1) {
    			// If we have an LED, match its state to the button's. 
    			int val = gpio_pin_get_dt(&button);
                            
    			if (val >= 0) {
    				gpio_pin_set_dt(&led, val);
    			}
    			k_msleep(SLEEP_TIME_MS);
    		}
    	}*/
            printk("Starting BLE Service\n");
            err = bt_enable(bt_ready_data_data_data_data_work_work_work_work_fn);
    
    	if (err) 
    	{
    		printk("BLE initialization failed (err %d)\n", err);
    		error(); //Catch error
    	}
    	/* 	Bluetooth stack should be ready in less than 100 msec. 					\
    																							\
    		We use this semaphore to wait for bt_enable to call bt_ready before we proceed 		\
    		to the main loop. By using the semaphore to block execution we allow the RTOS to 	\
    		execute other tasks while we wait. */	
    	err = k_sem_take(&ble_init_ok, K_MSEC(500));
                    
    	if (!err) 
    	{
    		printk("Bluetooth initialized\n");
    	} else 
    	{
    		printk("BLE initialization did not complete in time\n");
    		error(); //Catch error
    	}
    
    
    
    	for (;;) 
    	{
    		// Main loop
    		//my_service_send(my_connection, (uint8_t *)&number, sizeof(number));
    		number++;
    		k_sleep(K_MSEC(1000)); // 1000ms
    	}
    
    	const char *const label = DT_LABEL(DT_INST(0, invensense_mpu6050));
    	const struct device *mpu6050 = device_get_binding(label);
    
    	if (!mpu6050) {
                    printf("All sensors configured %s\n", label);
    		//printf("Failed to find sensor %s\n", label);
    		return;
    	}
    
    #ifdef CONFIG_MPU6050_TRIGGER
    	trigger = (struct sensor_trigger) {
    		.type = SENSOR_TRIG_DATA_READY,
    		.chan = SENSOR_CHAN_ALL,
    	};
    	if (sensor_trigger_set(mpu6050, &trigger,
    			       handle_mpu6050_drdy) < 0) {
    		printf("Cannot configure trigger\n");
    		return;
    	}
    	printk("Configured for triggered sampling.\n");
    #endif
    
    	while (!IS_ENABLED(CONFIG_MPU6050_TRIGGER)) {
    		int rc = process_mpu6050(mpu6050);
    
    		if (rc != 0) {
    			break;
    		}
    		k_sleep(K_SECONDS(2));
    	}
    
    }

    is there something we can do to make it clean and therefore to get the BT to work ?
    thank you in advance 

Reply
  • here's my updated code 

    #include <zephyr.h>
    #include <device.h>
    #include <drivers/sensor.h>
    #include <stdio.h>
    #include <sys/util.h>
    #include <sys/printk.h>
    #include <inttypes.h>
    #include <drivers/gpio.h>
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/byteorder.h>
    #include <soc.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/hci.h>
    #include <bluetooth/conn.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    
    #include "C:/sdk/v1.9.0/zephyr/samples/sensor/inaa219/services/my_service.h"
    
    #define DEVICE_NAME 		CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN 		(sizeof(DEVICE_NAME) - 1)
    
    #define SLEEP_TIME_MS	1
    
    /*
     * Get button configuration from the devicetree sw0 alias. This is mandatory.
     Replace DT_ALIAS(sw0) by sw27 to get output through SCT click
     */
    #define MY_SERVICE_UUID 0x0001
    #define SW0_NODE	DT_ALIAS(sw0)
    #if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
    #error "Unsupported board: sw0 devicetree alias is not defined"
    #endif
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,
    							      {0});
    static struct gpio_callback button_cb_data;
    static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
    						     {0});
    static int on_click = 1;
    
    #define APP_WORK_QUEUE_SIZE 4096	
    #define APP_WORK_QUEUE_PRI -1
    
    K_THREAD_STACK_DEFINE(application_stack_area, APP_WORK_QUEUE_SIZE);	
    			 
    static struct k_work_q application_work_q;
    static struct k_work bt_ready_data_data_data_data_work;
    static struct k_work get_ina219_data_data_data_work;
    //static struct k_work get_bme280_data_data_work;
    static struct k_work get_mpu6050_data_work;	
    
    static K_SEM_DEFINE(ble_init_ok, 0, 1);
    
    static const struct bt_data ad[] = 
    {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = 
    {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, MY_SERVICE_UUID),
    };
    struct bt_conn *my_connection;
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	my_connection = conn;
    
    	if (err) 
    	{
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    	else if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection established!		\n\
    		Connected to: %s			\n\
    		Role: %u				\n\
    		Connection interval: %u			\n\
    		Slave latency: %u                       \n\
    		Connection supervisory timeout: %u	\n"
    		, addr, info.role, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    }
    
    static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
    {
    	//If acceptable params, return true, otherwise return false.
    	return true; 
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, uint16_t timeout)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    	
    	if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection parameters updated!	\n\
    		Connected to: %s			\n\
    		New Connection Interval: %u		\n\
    		New Slave Latency: %u			\n\
    		New Connection Supervisory Timeout: %u	\n"
    		, addr, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static struct bt_conn_cb conn_callbacks = 
    {
    	.connected			= connected,
    	.disconnected   		= disconnected,
    	.le_param_req			= le_param_req,
    	.le_param_updated		= le_param_updated
    };
    
    static const char *now_str(void)
    {
    	static char buf[16]; /* ...HH:MM:SS.MMM */
    	uint32_t now = k_uptime_get_32();
    	unsigned int ms = now % MSEC_PER_SEC;
    	unsigned int s;
    	unsigned int min;
    	unsigned int h;
    
    	now /= MSEC_PER_SEC;
    	s = now % 60U;
    	now /= 60U;
    	min = now % 60U;
    	now /= 60U;
    	h = now;
    
    	snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
    		 h, min, s, ms);
    	return buf;
    }
    
    static int process_mpu6050(const struct device *dev)
    {
    	struct sensor_value temperature;
    	struct sensor_value accel[3];
    	struct sensor_value gyro[3];
    	int rc = sensor_sample_fetch(dev);
    
    	if (rc == 0) {
    		rc = sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ,
    					accel);
    	}
    	if (rc == 0) {
    		rc = sensor_channel_get(dev, SENSOR_CHAN_GYRO_XYZ,
    					gyro);
    	}
    	if (rc == 0) {
    		rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP,
    					&temperature);
    	}
    	if (rc == 0) {
    		printf("[%s]:%g Cel\n"
    		       "  accel %f %f %f m/s/s\n"
    		       "  gyro  %f %f %f rad/s\n",
    		       now_str(),
    		       sensor_value_to_double(&temperature),
    		       sensor_value_to_double(&accel[0]),
    		       sensor_value_to_double(&accel[1]),
    		       sensor_value_to_double(&accel[2]),
    		       sensor_value_to_double(&gyro[0]),
    		       sensor_value_to_double(&gyro[1]),
    		       sensor_value_to_double(&gyro[2]));
    	} else {
    		printf("sample fetch/get failed: %d\n", rc);
    	}
    
    	return rc;
    }
    
    #ifdef CONFIG_MPU6050_TRIGGER
    static struct sensor_trigger trigger;
    
    static void handle_mpu6050_drdy(const struct device *dev,
    				struct sensor_trigger *trig)
    {
    	int rc = process_mpu6050(dev);
    
    	if (rc != 0) {
    		printf("cancelling trigger due to failure: %d\n", rc);
    		(void)sensor_trigger_set(dev, trig, NULL);
    		return;
    	}
    }
    #endif /* CONFIG_MPU6050_TRIGGER */
    
    static const struct device *get_ina219_device(void)
    {
      const struct device *dev = DEVICE_DT_GET_ANY(ti_ina219);
            if(dev == NULL){
                      printk("\nEror: no device found. \n");
                      return NULL;
             }
             if (!device_is_ready(dev)) {
    		printk("\nError: Device \"%s\" is not ready; "
    		       "check the driver initialization logs for errors.\n",
    		       dev->name);
    		return NULL;
    	}
    
    	//printk("Found device \"%s\", getting sensor data\n", dev->name);
    	return dev;
    }
    
    /*static const struct device *get_bme280_device(void)
    {
    	const struct device *dev = DEVICE_DT_GET_ANY(bosch_bme280);
    
    	if (dev == NULL) {
    		// No such node, or the node does not have status "okay". 
    		printk("\nError: no device found.\n");
    		return NULL;
    	}
    
    	if (!device_is_ready(dev)) {
    		printk("\nError: Device \"%s\" is not ready; "
    		       "check the driver initialization logs for errors.\n",
    		       dev->name);
    		return NULL;
    	}
    
    	//printk("Found device \"%s\", getting sensor data\n", dev->name);
    	return dev;
    }*/
    
    static void get_mpu6050_data_work_fn(struct k_work *work)
    {
            
    	printk("-----------------Get MPU6050 data\n" );
    
            struct sensor_value temperature;
            struct sensor_value accel[3];
            struct sensor_value gyro[3];
    
            printf("[%s]:%g Cel\n"
    	"  accel %f %f %f m/s/s\n"
    	"  gyro  %f %f %f rad/s\n",
    	now_str(),
    	sensor_value_to_double(&temperature),
    	sensor_value_to_double(&accel[0]),
    	sensor_value_to_double(&accel[1]),
    	sensor_value_to_double(&accel[2]),
    	sensor_value_to_double(&gyro[0]),
    	sensor_value_to_double(&gyro[1]),
    	sensor_value_to_double(&gyro[2]));
    	
    }
    
    /*static void get_bme280_data_data_work_work_fn(struct k_work *work)
    {
                    printk("+++++++++++++++++Get BME280 data\n");
                    
    		struct sensor_value temp, press, humidity;
    		sensor_sample_fetch(get_bme280_device());
    		sensor_channel_get(get_bme280_device(), SENSOR_CHAN_AMBIENT_TEMP, &temp);
    		sensor_channel_get(get_bme280_device(), SENSOR_CHAN_PRESS, &press);
    		sensor_channel_get(get_bme280_device(), SENSOR_CHAN_HUMIDITY, &humidity);
    
    		printk("temp: %d.%06d; press: %d.%06d; humidity: %d.%06d\n",
    		      temp.val1, temp.val2, press.val1, press.val2,
    		      humidity.val1, humidity.val2);
    	
    }*/
    
    static void get_ina219_data_data_data_work_work_work_fn(struct k_work *work)
    {
          printk("################Get INA219 data\n");
    
          struct sensor_value v_bus, power, current;
          sensor_sample_fetch(get_ina219_device());
                    sensor_channel_get(get_ina219_device(), SENSOR_CHAN_VOLTAGE, &v_bus);
    		sensor_channel_get(get_ina219_device(), SENSOR_CHAN_POWER, &power);
    		sensor_channel_get(get_ina219_device(), SENSOR_CHAN_CURRENT, &current);
          
    		printf("Bus: %f [V] -- "
    			"Power: %f [W] -- "
    			"Current: %f [A]\n",
    		       sensor_value_to_double(&v_bus),
    		       sensor_value_to_double(&power),
    		       sensor_value_to_double(&current));
    }
    
    static void error(void)
    {
    	while (true) {
    		printk("Error!\n");
    		/* Spin for ever */
    		k_sleep(K_MSEC(1000)); //1000ms
    	}
    }
    
    void button_pressed(const struct device *dev, struct gpio_callback *cb,
    		    uint32_t pins)
    {
            printk("***************Button pressed at ");
            int val = gpio_pin_get_dt(&button);
            if(val == 1){
            gpio_pin_set_dt(&button, val);
            printk("Number of cycle : %d\n", on_click++);
            }
            else if (val == 0){
            printk("Number of cycle : %d\n", on_click);
            }
    	k_work_submit_to_queue(&application_work_q, &get_mpu6050_data_work);
            //k_work_submit_to_queue(&application_work_q, &get_bme280_data_data_work);
            k_work_submit_to_queue(&application_work_q, &get_ina219_data_data_data_work);
            k_work_submit_to_queue(&application_work_q, &bt_ready_data_data_data_data_work);
            
    }
    static void bt_ready_data_data_data_data_work_work_work_work_fn(int err)
    {
    	if (err) 
    	{
    		printk("BLE init failed with error code %d\n", err);
    		return;
    	}
    	//Configure connection callbacks
            printk("callbacks");
    	bt_conn_cb_register(&conn_callbacks);
    	//Initalize services
            printk("initialisation");
    	err = my_service_init();
            printk("LBS \n");
           
    	//Start advertising
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
            printk("BT Starting \n");  
    	if (err) 
    	{
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
            else{
    	printk("Advertising successfully started\n");
            }
    	k_sem_give(&ble_init_ok);
    }
    
    static void work_init(void)
    {
    	k_work_init(&get_mpu6050_data_work, get_mpu6050_data_work_fn);
    	//k_work_init(&get_bme280_data_data_work, get_bme280_data_data_work_work_fn);
            k_work_init(&get_ina219_data_data_data_work, get_ina219_data_data_data_work_work_work_fn);
            k_work_init(&bt_ready_data_data_data_data_work, bt_ready_data_data_data_data_work_work_work_work_fn);
    }
    
    void main(void)
    {
    	int ret;       
            int err = 0;
    	uint32_t number = 0;
    
    	k_work_queue_start(&application_work_q, application_stack_area,
    			K_THREAD_STACK_SIZEOF(application_stack_area),
    			APP_WORK_QUEUE_PRI, NULL);
    	work_init();
    
    	if (!device_is_ready(button.port)) {
    		printk("Error: button device %s is not ready\n",
    		       button.port->name);
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
    	if (ret != 0) {
    		printk("Error %d: failed to configure %s pin %d\n",
    		       ret, button.port->name, button.pin);
    		return;
    	}
    
    	ret = gpio_pin_interrupt_configure_dt(&button,
    					      GPIO_INT_EDGE_TO_ACTIVE);
    	if (ret != 0) {
    		printk("Error %d: failed to configure interrupt on %s pin %d\n",
    			ret, button.port->name, button.pin);
    		return;
    	}
    
    	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
    	gpio_add_callback(button.port, &button_cb_data);
    	printk("Set up button at %s pin %d\n", button.port->name, button.pin);
    
    	if (led.port && !device_is_ready(led.port)) {
    		printk("Error %d: LED device %s is not ready; ignoring it\n",
    		       ret, led.port->name);
    		led.port = NULL;
    	}
    	if (led.port) {
    		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
    		if (ret != 0) {
    			printk("Error %d: failed to configure LED device %s pin %d\n",
    			       ret, led.port->name, led.pin);
    			led.port = NULL;
    		} else {
    			printk("Set up LED at %s pin %d\n", led.port->name, led.pin);
    		}
    	}
    
    	printk("Press the button\n");
    	/*if (led.port) {
    		while (1) {
    			// If we have an LED, match its state to the button's. 
    			int val = gpio_pin_get_dt(&button);
                            
    			if (val >= 0) {
    				gpio_pin_set_dt(&led, val);
    			}
    			k_msleep(SLEEP_TIME_MS);
    		}
    	}*/
            printk("Starting BLE Service\n");
            err = bt_enable(bt_ready_data_data_data_data_work_work_work_work_fn);
    
    	if (err) 
    	{
    		printk("BLE initialization failed (err %d)\n", err);
    		error(); //Catch error
    	}
    	/* 	Bluetooth stack should be ready in less than 100 msec. 					\
    																							\
    		We use this semaphore to wait for bt_enable to call bt_ready before we proceed 		\
    		to the main loop. By using the semaphore to block execution we allow the RTOS to 	\
    		execute other tasks while we wait. */	
    	err = k_sem_take(&ble_init_ok, K_MSEC(500));
                    
    	if (!err) 
    	{
    		printk("Bluetooth initialized\n");
    	} else 
    	{
    		printk("BLE initialization did not complete in time\n");
    		error(); //Catch error
    	}
    
    
    
    	for (;;) 
    	{
    		// Main loop
    		//my_service_send(my_connection, (uint8_t *)&number, sizeof(number));
    		number++;
    		k_sleep(K_MSEC(1000)); // 1000ms
    	}
    
    	const char *const label = DT_LABEL(DT_INST(0, invensense_mpu6050));
    	const struct device *mpu6050 = device_get_binding(label);
    
    	if (!mpu6050) {
                    printf("All sensors configured %s\n", label);
    		//printf("Failed to find sensor %s\n", label);
    		return;
    	}
    
    #ifdef CONFIG_MPU6050_TRIGGER
    	trigger = (struct sensor_trigger) {
    		.type = SENSOR_TRIG_DATA_READY,
    		.chan = SENSOR_CHAN_ALL,
    	};
    	if (sensor_trigger_set(mpu6050, &trigger,
    			       handle_mpu6050_drdy) < 0) {
    		printf("Cannot configure trigger\n");
    		return;
    	}
    	printk("Configured for triggered sampling.\n");
    #endif
    
    	while (!IS_ENABLED(CONFIG_MPU6050_TRIGGER)) {
    		int rc = process_mpu6050(mpu6050);
    
    		if (rc != 0) {
    			break;
    		}
    		k_sleep(K_SECONDS(2));
    	}
    
    }

    is there something we can do to make it clean and therefore to get the BT to work ?
    thank you in advance 

Children
  • I do not see anything obviously very wrong in the Bluetooth related code now (though there are a few other things worth noting for a different time). Does it build without warnings now? What happens runtime and what do you see when debugging?

    Note the code I posted before, which was basically your code just with the non-BLE part stripped out, and a few issues fixed. And that works fine. I recommend you to test it and compare with your won code. Or perhaps start with that, observe that it is working, and put back things from your original code gradually while checking that nothing breaks. That way I expect you will get this working quickly.

  • followed the same article. built the code. no warning. same output (err -11).

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <soc.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    #include <zephyr/settings/settings.h>
    
    
    #define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)
    
    #define MAX_TRANSMIT_SIZE 240
    uint8_t data_rx[MAX_TRANSMIT_SIZE];
    uint8_t data_tx[MAX_TRANSMIT_SIZE];
    
    #define MY_SERVICE_UUID 				0xd4, 0x86, 0x48, 0x24, 0x54, 0xB3, 0x43, 0xA1, 0xBC, 0x20, 0x97, 0x8F, 0xC3, 0x76, 0xC2, 0x75
    #define RX_CHARACTERISTIC_UUID 			0xA6, 0xE8, 0xC4, 0x60, 0x7E, 0xAA, 0x41, 0x6B, 0x95, 0xD4, 0x9D, 0xCC, 0x08, 0x4F, 0xCF, 0x6A
    #define TX_CHARACTERISTIC_UUID 			0xED, 0xAA, 0x20, 0x11, 0x92, 0xE7, 0x43, 0x5A, 0xAA, 0xE9, 0x94, 0x43, 0x35, 0x6A, 0xD4, 0xD3
    
    #define BT_UUID_MY_SERIVCE      BT_UUID_DECLARE_128(MY_SERVICE_UUID)
    #define BT_UUID_MY_SERIVCE_RX   BT_UUID_DECLARE_128(RX_CHARACTERISTIC_UUID)
    #define BT_UUID_MY_SERIVCE_TX   BT_UUID_DECLARE_128(TX_CHARACTERISTIC_UUID)
    
    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, MY_SERVICE_UUID),
    };
    
    
    
    struct bt_conn *my_connection;
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	my_connection = conn;
    
    	if (err) 
    	{
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    	else if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection established!		\n\
    		Connected to: %s					\n\
    		Role: %u							\n\
    		Connection interval: %u				\n\
    		Slave latency: %u					\n\
    		Connection supervisory timeout: %u	\n"
    		, addr, info.role, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    
    	my_connection = NULL;
    }
    
    static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
    {
    	//If acceptable params, return true, otherwise return false.
    	return true; 
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, uint16_t timeout)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    	
    	if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection parameters updated!	\n\
    		Connected to: %s						\n\
    		New Connection Interval: %u				\n\
    		New Slave Latency: %u					\n\
    		New Connection Supervisory Timeout: %u	\n"
    		, addr, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    
    static struct bt_conn_cb conn_callbacks = {
    	.connected		    = connected,
    	.disconnected   	= disconnected,
    	.le_param_req		= le_param_req,
    	.le_param_updated	= le_param_updated
    };
    
    
    
    
    
    
    int my_service_init(void)
    {
        int err = 0;
       
        memset(&data_rx, 0, MAX_TRANSMIT_SIZE);
        memset(&data_tx, 0, MAX_TRANSMIT_SIZE);
        
        return err;
    }
    
    static ssize_t on_receive(struct bt_conn *conn,
    			  const struct bt_gatt_attr *attr,
    			  const void *buf,
    			  uint16_t len,
    			  uint16_t offset,
    			  uint8_t flags)
    {
        const uint8_t * buffer = buf;
        
    	printk("Received data, handle %d, conn %p, data: 0x", attr->handle, conn);
        for(uint8_t i = 0; i < len; i++){
            printk("%02X", buffer[i]);
        }
        printk("\n");
    
    	return len;
    }
    
    static void on_sent(struct bt_conn *conn, void *user_data)
    {
    	ARG_UNUSED(user_data);
    
        const bt_addr_le_t * addr = bt_conn_get_dst(conn);
            
    	printk("Data sent to Address 0x %02X %02X %02X %02X %02X %02X \n", addr->a.val[0]
                                                                        , addr->a.val[1]
                                                                        , addr->a.val[2]
                                                                        , addr->a.val[3]
                                                                        , addr->a.val[4]
                                                                        , addr->a.val[5]);
    }
    
    /* This function is called whenever the CCCD register has been changed by the client*/
    void on_cccd_changed(const struct bt_gatt_attr *attr, uint16_t value)
    {
        ARG_UNUSED(attr);
        switch(value)
        {
            case BT_GATT_CCC_NOTIFY: 
                // Start sending stuff!
                break;
    
            case BT_GATT_CCC_INDICATE: 
                // Start sending stuff via indications
                break;
    
            case 0: 
                // Stop sending stuff
                break;
            
            default: 
                printk("Error, CCCD has been set to an invalid value");     
        }
    }
                            
    
    /* LED Button Service Declaration and Registration */
    BT_GATT_SERVICE_DEFINE(my_service,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_MY_SERIVCE),    
    BT_GATT_CHARACTERISTIC(BT_UUID_MY_SERIVCE_RX,
    			       BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
    			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, 
                       NULL, on_receive, NULL),
    BT_GATT_CHARACTERISTIC(BT_UUID_MY_SERIVCE_TX,
    			       BT_GATT_CHRC_NOTIFY,
    			       BT_GATT_PERM_READ,
                       NULL, NULL, NULL),
    BT_GATT_CCC(on_cccd_changed,
            BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
    );
    
    /* This function sends a notification to a Client with the provided data,
    given that the Client Characteristic Control Descripter has been set to Notify (0x1).
    It also calls the on_sent() callback if successful*/
    void my_service_send(struct bt_conn *conn, const uint8_t *data, uint16_t len)
    {
        /* 
        The attribute for the TX characteristic is used with bt_gatt_is_subscribed 
        to check whether notification has been enabled by the peer or not.
        Attribute table: 0 = Service, 1 = Primary service, 2 = RX, 3 = TX, 4 = CCC.
        */
        const struct bt_gatt_attr *attr = &my_service.attrs[3]; 
    
        struct bt_gatt_notify_params params = 
        {
            .uuid   = BT_UUID_MY_SERIVCE_TX,
            .attr   = attr,
            .data   = data,
            .len    = len,
            .func   = on_sent
        };
    
        // Check whether notifications are enabled or not
        if(bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) 
        {
            // Send the notification
    	    if(bt_gatt_notify_cb(conn, &params))
            {
                printk("Error, unable to send notification\n");
            }
        }
        else
        {
            printk("Warning, notification not enabled on the selected attribute\n");
        }
    }
    
    
    
    
    
    
    
    
    
    int main(void)
    {
    	int err;
    
    	printk("Starting Bluetooth Peripheral LBS example\n");
    
    
    
    
    	k_msleep(1000);
    	err = bt_enable(NULL);
    	if (err) {
    		printk("INIT: Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    	else
    	{
    		printk("INIT: Bluetooth initialized %d\n", err);
    	}
    
    	//Configure connection callbacks
    	bt_conn_cb_register(&conn_callbacks);
    
    	//Initalize services
    	err = my_service_init();
    
    	if (err) 
    	{
    		printk("Failed to init LBS (err:%d)\n", err);
    		return;
    	}
    
    	//Start advertising
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
    	if (err) 
    	{
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Advertising successfully started\n");
    
    
    
    
    
    	if (!err) 
    	{
    		printk("Bluetooth initialized\n");
    	} else 
    	{
    		printk("BLE initialization did not complete in time\n");
    	}
    
    	printk("Bluetooth initialized\n");
    
    	my_service_init();
    
    
    
    
    
    	uint32_t counter = 0;
    	for (;;) {
    		printk("NET LOOP %u\n", ++counter);
    		k_sleep(K_MSEC(1000));
    	}
    }
    

  • as usual, as soon as I post on a support forum, i find the solution in the next 3 minutes.

    the code produced a log that stated "[00:00:01.450,439] <inf> bt_hci_core: bt_init: No ID address. App must call settings_load()"

    which is weird, because in my conf file i have.

    CONFIG_SETTINGS=n

    Furthermore, nrf samples all have something like

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

    So I didn't put that in the code.

    Apparently calling settings_load is what the code was missing. probably the sample was written for an old version of zephyr.


    The complete main is:


    
    
    int main(void)
    {
    	int err;
    
    	printk("Starting Bluetooth Peripheral LBS example\n");
    
    
    
    
    	k_msleep(1000);
    	err = bt_enable(NULL);
    	if (err) {
    		printk("INIT: Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    	else
    	{
    		printk("INIT: Bluetooth initialized %d\n", err);
    	}
    
    	//Configure connection callbacks
    	bt_conn_cb_register(&conn_callbacks);
    
    	//Initalize services
    	err = my_service_init();
    
    	if (err) 
    	{
    		printk("Failed to init LBS (err:%d)\n", err);
    		return;
    	}
    
    
    	settings_load();
    
    	//Start advertising
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
    	if (err) 
    	{
    		printk("Advertising failed to start (err %d)\n", err);
    		while(1);
    	}
    
    	
    
    	if (!err) 
    	{
    		printk("Bluetooth initialized\n");
    	} else 
    	{
    		printk("BLE initialization did not complete in time\n");
    	}
    
    	printk("Bluetooth initialized\n");
    
    	my_service_init();
    
    	uint32_t counter = 0;
    	for (;;) {
    		printk("NET LOOP %u\n", ++counter);
    		k_sleep(K_MSEC(1000));
    	}
    }


    Apologies for the sloppy as hell code, I just copy pasted everything in the main.c.
Related