I using NCS V2.1.2 toolchain and two nrf52840_dongle and following this tutorial: https://webinars.nordicsemi.com/developing-bluetooth-low-energy-6
First dongle follow the code on tutorial and second dongle using nrf connect desktop bluetooth low energy.
Because using dongle instead of nrf52840-DK i was implement USB CDC ACM console follow example code (for debug), it work well and i can get log information on nRF Terminal .
For button pressed function i add to gpio callback, when press button variable btn_count increase then send to desktop bluetooth app
If i do not enable notification on desktop bluetooth app, i can send data by press button on first dongle then pressing read button on desktop bluetooth app, i can send data back from desktop bluetooth app to peripheral (the first dongle) like tutorial does.
But, when i enable notification on desktop bluetooth app then press button on peripheral it will reboot immediate, i still can send data from desktop bluetooth app to peripheral normal, only reboot when press button and enable notification.
if i put this code in while of main:
k_sleep(K_SECONDS(1)); btn_count++; send_button_notification(current_conn, btn_count, 1);
#include <zephyr/zephyr.h>
#include <zephyr/sys/printk.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/drivers/uart.h>
#include <logging/log.h>
#include <zephyr/drivers/gpio.h>
#include "remote.h"
BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart),
"Console device is not ACM CDC UART device");
#define LED0_NODE DT_ALIAS(led0)
#define SW0_NODE DT_ALIAS(sw0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led1_blue = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led3), gpios, {0});
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
// static struct gpio_dt_spec button = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); //OK
static struct gpio_callback button_cb_data;
uint8_t btn_count=0;
#define LOG_MODULE_NAME app
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);
struct bt_conn *current_conn;
void on_connected(struct bt_conn *conn, uint8_t err);
void on_disconnected(struct bt_conn *conn, uint8_t reason);
void on_notif_changed(enum bt_button_notifications_enabled status);
void on_data_received(struct bt_conn *conn, const uint8_t *const data, uint16_t len);
struct bt_conn_cb bluetooth_callbacks = {
.connected = on_connected,
.disconnected = on_disconnected,
// .le_param_req = le_param_req,
// .le_param_updated = le_param_updated
};
struct bt_remote_service_cb remote_callbacks = {
.notif_changed = on_notif_changed,
.data_received = on_data_received,
};
void on_connected(struct bt_conn *conn, uint8_t err){
struct bt_conn_info info;
if(err){
LOG_INF("connection err %d", err);
return;
}
LOG_INF("Connected OK");
current_conn = bt_conn_ref(conn);
gpio_pin_set(led.port, led.pin, 1); //on led
}
void on_disconnected (struct bt_conn *conn, uint8_t reason){
LOG_INF("On disconnected, reason %d", reason);
if (current_conn){
bt_conn_unref(current_conn);
current_conn = NULL;
}
gpio_pin_set_dt(&led, 0); //off led
}
void on_notif_changed(enum bt_button_notifications_enabled status){
if (status == BT_BUTTON_NOTIFICATIONS_ENABLED){
LOG_INF("Notification enabled");
} else {
LOG_INF("Notifications disable");
}
}
void on_data_received(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
{
uint8_t temp_str[len+1];
memcpy(temp_str, data, len);
temp_str[len] = 0x00;
LOG_INF("Received data on conn %p. Len: %d", (void *)conn, len);
LOG_INF("Data: %s", temp_str);
}
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
int err=0;
uint32_t bit_to_pin = 0;
for (int i = 0; i < 32; i++) {
if ((pins >> i) == 1) {
bit_to_pin = i;
break;
}
}
// printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32()); //CDC ACM OK
gpio_pin_toggle(led.port, led.pin); //OK
btn_count++;
LOG_INF("Button %d pressed %d", bit_to_pin, btn_count);
set_button_value(btn_count);
err = send_button_notification(current_conn, btn_count, 1);
if (err){
LOG_ERR("couldn't send notification, err: %d", err);
}
}
void main(void)
{
int ret, err;
if (!device_is_ready(led.port)) return;
if (!device_is_ready(led1_blue.port)) {
return;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE); //init low
if (ret < 0) return;
gpio_pin_configure_dt(&led1_blue, GPIO_OUTPUT);
/* USB CDC ACM */
const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
uint32_t dtr = 0;
if (usb_enable(NULL)) {
return;
}
/* Poll if the DTR flag was set, chỗ này sẽ đợi mở terminal mới thực hiện tiếp */
while (!dtr) {
uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
/* Give CPU resources to low priority threads. */
k_sleep(K_MSEC(100));
}
/*************** end CDC ACM ***************/
LOG_INF("Hello CDC ACM BLE from: %s\n", CONFIG_BOARD);
if (!device_is_ready(button.port)) {
LOG_ERR("Error: button device %s is not ready\n",
button.port->name);
k_sleep(K_MSEC(5000));
return;
}
ret = gpio_pin_configure_dt(&button, GPIO_INPUT | GPIO_PULL_UP);
ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_RISING);
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
gpio_add_callback(button.port, &button_cb_data);
/*
*/
err = bluetooth_init(&bluetooth_callbacks, &remote_callbacks);
if (err){
LOG_ERR("Bluetooth returned %d", err);
}
LOG_INF("RUNNING");
while (1) {
// printk("Hello World! %s\n", CONFIG_ARCH);
k_sleep(K_SECONDS(1));
// k_sleep(K_MSEC(300));
// btn_count++;
// send_button_notification(current_conn, btn_count, 1);
gpio_pin_toggle_dt(&led1_blue);
}
}
