BLE communication of a Nordic nRF52840dk and Raspberry Pi 3

BLE communication of a Nordic nRF52840dk and Raspberry Pi 3

In this article we explore one example of BLE communication between an nRF52840 DK microcontroller from Nordic Semiconductor and a Raspberry Pi 3 Model B. The nRF52840, running Zephyr RTOS, acts as a BLE peripheral, sending data to the Raspberry Pi using the GATT protocol. The Raspberry Pi, running a Python script with the bluepy library, listens for notifications and visualizes the data using matplotlib.

nRF52840 Code (Zephyr RTOS)

The first part of the code runs on the nRF52840 microcontroller, which advertises itself as a BLE peripheral and sends data to the Raspberry Pi.

BLE Initialization:

The nRF52840 uses Zephyr's Bluetooth stack to initialize Bluetooth subsystem (bt_enable()) and set up the advertising data (bt_le_adv_start()).

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

Advertising:

The nRF52840 advertises its presence to nearby devices using the bt_le_adv_start() function. The advertisement includes a custom service UUID that the Raspberry Pi will later use to identify and interact with the peripheral.

err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0);        

Custom GATT Service:

A custom GATT service is defined, which includes a characteristic that can be read by the Raspberry Pi. The characteristic holds a double value, which is updated and sent periodically to the Raspberry Pi.

BT_GATT_CHARACTERISTIC(&custom_char_uuid.uuid,
                       BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
                       BT_GATT_PERM_READ,
                       read_custom_val, NULL, &custom_value)        

Handling Connections:

The connected and disconnected callbacks are set up to handle BLE connections. The peripheral waits for connections only from the Raspberry Pi(thus used filtering with bt_le_filter_accept_list_add() where manually added bt_address of Rpi), and once connected, it begins sending data through the GATT notifications.

err = bt_le_filter_accept_list_add(&rpi_mac);
if (err) {
    printk("Failed to add RPi to accept list (err %d)\n", err);
    return;
}        

Sending Data:

The custom_value variable, which holds a double, is periodically updated using the generate_random_double() function. The updated value is sent to the Raspberry Pi using GATT notifications.

bt_gatt_notify(NULL, &custom_svc.attrs[1], &custom_value, sizeof(double));        

Raspberry Pi Code (Python)

On the Raspberry Pi, we use Python to handle the BLE connection and visualize the data received.

Connecting to the BLE Peripheral:

The Peripheral class from the bluepy library is used for establishing the connection to the nRF52840. Raspberry Pi uses the peripheral's address (in this case, a random address-which we get from minicom which is monitoring nRF52840) to connect.

peripheral = Peripheral(nrf_address, addrType=ADDR_TYPE_RANDOM)        

Handling Notifications:

A custom NotificationDelegate class is created to handle incoming notifications from the nRF52840. When new data is received, it is unpacked and added to a queue for later processing.

def handleNotification(self, cHandle, data):
    if len(data) == 8: #ensure double variable.
        value = struct.unpack('<d', data)[0] 
        self.data_queue.append(value)        

Plotting:

Received data are plotted using matplotlib. The update_plot() function is used to dynamically update the plot every time new data is received. The FuncAnimation class is used for this.

ani = animation.FuncAnimation(fig, update_plot, fargs=(data_queue, line), interval=100)        

Running the Listener:

The ble_listener() function continuously listens for notifications from the nRF52840. It runs as separate thread for not blocking the execution while the plot is being updated.

ble_thread = threading.Thread(target=ble_listener, daemon=True)
ble_thread.start()        

Once the connection is established and notifications are being received, the Raspberry Pi creates the visualization showing the values received.

image from running the code.


要查看或添加评论,请登录

Nikos Mouzakitis的更多文章

社区洞察

其他会员也浏览了