examples of simple peripheral/central ble transmission nrf52 series

I am very familiar with PICs and some atmega stuff, just graduated university ee and the project I am working on requires transmitting very small amounts of data continuously via ble protocol. Actually transmitting real time gyroscope data. Nrf modules seemed the easiest/cheapest for our purpose and decided we would most likely end up going with someones 52 series module. I have been playing around awhile with the nordic 52 development board however I am finding the learning curve fairly steep with zephyr. I can do basic stuff, gpio, pwm, interrupts etc but am struggling with bluetooth. Would it be possible to get an example of a central device and peripheral device with a custom service and characteristic 128, that simply sends or receives 24 or more bits of data at a time.   I'm really trying to learn this and just feel myself lost, thanks.  I have been through many of the peripheral and central zephyr examples.

Parents
  • Hi,

    Yes, you may keep this ticket open if you would like so for follow up questions which are related to the topic in this ticket. If you have new questions, I will of course try to reply and answer to them, but I would recommend to create new tickets for unique questions and cases.

    And also yes, I would say this type of ticket is something that is perfect as a public ticket as there are very likely more out there with the same questions and in the same situation, so go ahead and convert it if you're comfortable with that!

    Kind regards,
    Andreas

  • after much experimenting I seem to be getting this error from the second example. 

  • ////this is .h
    
    #include <zephyr.h>
    #include <logging/log.h>
    
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    #include <bluetooth/hci.h>
    
    #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
    
    /** @brief Callback type for when new data is received. */
    typedef void (*data_rx_cb_t)(uint8_t *data, uint8_t length);
    
    /** @brief Callback struct used by the my_service Service. */
    struct my_service_cb 
    {
    	/** Data received callback. */
    	data_rx_cb_t    data_rx_cb;
    };
    
    int my_service_init(void);
    
    void my_service_send(struct bt_conn *conn, const uint8_t *data, uint16_t len);
    
    
    
    

  • ///main file
    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <logging/log.h>
    #include <dk_buttons_and_leds.h>
    #include "remote.h"
    
    
    #define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)
    
    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 bt_ready(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();
    
    	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");
    
    	k_sem_give(&ble_init_ok);
    }
    
    
    static void error(void)
    {
    	while (true) {
    		printk("Error!\n");
    		/* Spin for ever */
    		k_sleep(K_MSEC(1000)); //1000ms
    	}
    }
    
    void main(void)
    {
    	
    	int err = 0;
    	uint32_t number = 0;
    
    	printk("Starting Nordic BLE peripheral tutorial\n");
    
    	
    	err = bt_enable(bt_ready);
    
    	if (err) 
    	{
    		printk("BLE initialization failed\n");
    		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
    	}
    
    	err = my_service_init();
    
    	for (;;) 
    	{
    		// Main loop
    		my_service_send(my_connection, (uint8_t *)&number, sizeof(number));
    		number++;
    		k_sleep(K_MSEC(1000)); // 1000ms
    	}
    }

Reply
  • ///main file
    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <logging/log.h>
    #include <dk_buttons_and_leds.h>
    #include "remote.h"
    
    
    #define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)
    
    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 bt_ready(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();
    
    	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");
    
    	k_sem_give(&ble_init_ok);
    }
    
    
    static void error(void)
    {
    	while (true) {
    		printk("Error!\n");
    		/* Spin for ever */
    		k_sleep(K_MSEC(1000)); //1000ms
    	}
    }
    
    void main(void)
    {
    	
    	int err = 0;
    	uint32_t number = 0;
    
    	printk("Starting Nordic BLE peripheral tutorial\n");
    
    	
    	err = bt_enable(bt_ready);
    
    	if (err) 
    	{
    		printk("BLE initialization failed\n");
    		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
    	}
    
    	err = my_service_init();
    
    	for (;;) 
    	{
    		// Main loop
    		my_service_send(my_connection, (uint8_t *)&number, sizeof(number));
    		number++;
    		k_sleep(K_MSEC(1000)); // 1000ms
    	}
    }

Children
No Data
Related