Advanced
30 min

Achieve long-range BLE 5.1 communication with NINA-B416 and STM32F302VC

Secure, long-range Bluetooth LE and NFC solution for advanced embedded applications

NINA-B416 Click with CLICKER 4 for STM32F302VCT6

Published Jul 22, 2025

Click board™

NINA-B416 Click

Dev. board

CLICKER 4 for STM32F302VCT6

Compiler

NECTO Studio

MCU

STM32F302VC

Your go-to solution for secure, extended-range Bluetooth LE and NFC integration in demanding IoT environments

A

A

Hardware Overview

How does it work?

NINA-B416 Click is based on the NINA-B416, a professional-grade, stand-alone Bluetooth 5.1 Low Energy module from u-blox that integrates advanced features to ensure reliable wireless communication. The module operates with u-blox's u-connectXpress software, which greatly simplifies development by allowing easy configuration of connectivity parameters through AT commands via a standard UART interface. This software stack includes support for Bluetooth Low Energy Serial Port Service, full GATT client and server functionality, beacon operation, NFC integration, as well as the capability to operate in both peripheral and central roles simultaneously, offering maximum versatility for complex wireless topologies. With these capabilities, NINA-B416 Click is an ideal solution for applications in smart buildings, smart cities, industrial automation, sensor networks, and asset tracking, where reliable, secure, and long-range Bluetooth communication is essential. The NINA-B416 module incorporates advanced security features such as secure boot, ensuring that only authenticated u-connectXpress firmware is allowed to run, thus protecting the integrity of the system

from unauthorized code execution. The module's hardware design includes an integrated PCB antenna, delivering stable wireless performance without the need for external antenna components. Supporting Bluetooth output power of up to +11dBm and sensitivity levels reaching -95dBm at 1Mbit/s, the NINA-B416 module enables communication ranges of up to 1400 meters under optimal conditions, making it highly suitable for demanding environments where long-range connectivity is required. In addition, the module supports up to eight simultaneous Bluetooth connections, allowing efficient management of multiple devices within a network. This Click board™ establishes communication between the NINA-B416 module and the host MCU through a UART interface, using standard UART RX and TX pins and hardware flow control via CTS and RTS pins. The default communication speed is set at 115200bps, ensuring efficient data exchange. The NINA-B416 software extends the UART interface beyond the usual RX, TX, CTS, and RTS signals by including the DSR (Data Set Ready) and DTR (Data Terminal Ready) pins. Additionally, the Click

board™ includes a user-configurable RGB LED indicator labeled LD2, which indicates various module statuses, and two user-configurable buttons. In addition to the interface pins, the board features a reset (RST) pin for hard-resetting the module when necessary and SWD pads designed for use with MIKROE's 6-pin Needle Cable, providing an optional flash and debug SWD (Serial Wire Debug) interface functionality. NINA-B416 Click also includes u.Fl antenna for NFC support, that operates at 13.56MHz with a data rate of 106kbps. As an NFC tag, data can be read from NINA-B416 module using an NFC reader. The NINA-B416 module is not capable of reading other tags or initiating NFC communications. This Click board™ can be operated only with a 3.3V logic voltage level. The board must perform appropriate logic voltage level conversion before using MCUs with different logic levels. It also comes equipped with a library containing functions and example code that can be used as a reference for further development.

NINA-B416 Click hardware overview image

Features overview

Development board

Clicker 4 for STM32F3 is a compact development board designed as a complete solution, you can use it to quickly build your own gadgets with unique functionalities. Featuring a STM32F302VCT6, four mikroBUS™ sockets for Click boards™ connectivity, power managment, and more, it represents a perfect solution for the rapid development of many different types of applications. At its core, there is a STM32F302VCT6 MCU, a powerful microcontroller by STMicroelectronics, based on the high-

performance Arm® Cortex®-M4 32-bit processor core operating at up to 168 MHz frequency. It provides sufficient processing power for the most demanding tasks, allowing Clicker 4 to adapt to any specific application requirements. Besides two 1x20 pin headers, four improved mikroBUS™ sockets represent the most distinctive connectivity feature, allowing access to a huge base of Click boards™, growing on a daily basis. Each section of Clicker 4 is clearly marked, offering an intuitive and clean interface. This makes working with the development

board much simpler and thus, faster. The usability of Clicker 4 doesn’t end with its ability to accelerate the prototyping and application development stages: it is designed as a complete solution which can be implemented directly into any project, with no additional hardware modifications required. Four mounting holes [4.2mm/0.165”] at all four corners allow simple installation by using mounting screws. For most applications, a nice stylish casing is all that is needed to turn the Clicker 4 development board into a fully functional, custom design.

CLICKER 4 for STM32F302VCT6 double image

Microcontroller Overview

MCU Card / MCU

STM32F302VC Image

Architecture

ARM Cortex-M4

MCU Memory (KB)

256

Silicon Vendor

STMicroelectronics

Pin count

100

RAM (Bytes)

40960

You complete me!

Accessories

RFID tag operating at 13.56MHz adheres to the ISO14443-A standard, ensuring high-frequency communication. This proximity card technology, often exemplified by MIFARE cards, facilitates secure and contactless interactions in applications like access control, public transport, and payment systems. The ISO14443-A standard defines the communication protocol, incorporating anti-collision mechanisms for simultaneous card handling. These RFID tags possess variable memory capacities, ranging from a few bytes to kilobytes, catering to diverse application needs. Ensuring data security, the standard integrates features such as encryption and authentication. These tags, exemplified by MIFARE technology, are widely used for their efficiency and are vital in enhancing convenience and security in diverse identification and access scenarios.

NINA-B416 Click accessories 1 image

Circular NFC R25 Antenna is PCB antenna designed with the intention to be used as extension of development boards and placed remotely on desired place such as plastic casing, existing products, or even under displays. Antenna is designed in circular shape with diameter of 25mm. Its important to mention that this antenna can be used for NFC and RFID applications that works on 13.56MHz frequency.

NINA-B416 Click accessories 2 image

6-pin Needle Cable is a compact programming cable made from high-quality materials for longevity and easy portability with a tiny square footprint, similar to a 0805 resistor. Designed for quick programming and debugging, it features a 6-pin 0.1″ pitch ribbon connector and is hand-held or temporarily fixable.

NINA-B416 Click accessories 3 image

Used MCU Pins

mikroBUS™ mapper

Data Terminal Ready
PC4
AN
Reset / ID SEL
PC15
RST
UART CTS / ID COMM
PA4
CS
NC
NC
SCK
NC
NC
MISO
NC
NC
MOSI
Power Supply
3.3V
3.3V
Ground
GND
GND
Data Set Ready
PE9
PWM
UART RTS
PD0
INT
UART TX
PA2
TX
UART RX
PA3
RX
NC
NC
SCL
NC
NC
SDA
NC
NC
5V
Ground
GND
GND
1

Take a closer look

Click board™ Schematic

NINA-B416 Click Schematic schematic

Step by step

Project assembly

PIC32MZ MXS Data Capture Board front image hardware assembly

Start by selecting your development board and Click board™. Begin with the CLICKER 4 for STM32F302VCT6 as your development board.

PIC32MZ MXS Data Capture Board front image hardware assembly
Thermo 21 Click front image hardware assembly
Thermo 21 Click complete accessories setup image hardware assembly
Board mapper by product6 hardware assembly
Necto image step 2 hardware assembly
Necto image step 3 hardware assembly
Necto image step 4 hardware assembly
Necto image step 5 hardware assembly
Necto image step 6 hardware assembly
PIC32MZ MXS Data Capture Board NECTO MCU Selection Step hardware assembly
Necto No Display image step 8 hardware assembly
Necto image step 9 hardware assembly
Necto image step 10 hardware assembly
Necto image step 11 hardware assembly

Track your results in real time

Application Output

1. Application Output - In Debug mode, the 'Application Output' window enables real-time data monitoring, offering direct insight into execution results. Ensure proper data display by configuring the environment correctly using the provided tutorial.

2. UART Terminal - Use the UART Terminal to monitor data transmission via a USB to UART converter, allowing direct communication between the Click board™ and your development system. Configure the baud rate and other serial settings according to your project's requirements to ensure proper functionality. For step-by-step setup instructions, refer to the provided tutorial.

3. Plot Output - The Plot feature offers a powerful way to visualize real-time sensor data, enabling trend analysis, debugging, and comparison of multiple data points. To set it up correctly, follow the provided tutorial, which includes a step-by-step example of using the Plot feature to display Click board™ readings. To use the Plot feature in your code, use the function: plot(*insert_graph_name*, variable_name);. This is a general format, and it is up to the user to replace 'insert_graph_name' with the actual graph name and 'variable_name' with the parameter to be displayed.

Software Support

Library Description

NINA-B416 Click demo application is developed using the NECTO Studio, ensuring compatibility with mikroSDK's open-source libraries and tools. Designed for plug-and-play implementation and testing, the demo is fully compatible with all development, starter, and mikromedia boards featuring a mikroBUS™ socket.

Example Description
This example demonstrates the use of NINA-B416 Click board by processing data from a connected BT device.

Key functions:

  • ninab416_cfg_setup - This function initializes Click configuration structure to initial values.

  • ninab416_init - This function initializes all necessary pins and peripherals used for this Click board.

  • ninab416_cmd_run - This function sends a specified command to the Click module.

  • ninab416_cmd_set - This function sets a value to a specified command of the Click module.

  • ninab416_cmd_get - This function is used to get the value of a given command from the Click module.

Application Init
Initializes the driver and logger.

Application Task
Application task is split in few stages:

  • NINAB416_POWER_UP - Powers up the device, performs a factory reset and reads system information.

  • NINAB416_EXAMPLE - Performs a BT terminal example by processing all data from a connected BT device and sending back an adequate response messages.

Open Source

Code example

The complete application code and a ready-to-use project are available through the NECTO Studio Package Manager for direct installation in the NECTO Studio. The application code can also be found on the MIKROE GitHub account.

/*!
 * @file main.c
 * @brief NINA-B416 Click Example.
 *
 * # Description
 * This example demonstrates the use of NINA-B416 Click board by processing data
 * from a connected BT device.
 *
 * The demo application is composed of two sections :
 *
 * ## Application Init
 * Initializes the driver and logger.
 *
 * ## Application Task
 * Application task is split in few stages:
 *  - NINAB416_POWER_UP:
 * Powers up the device, performs a factory reset and reads system information.
 *  - NINAB416_EXAMPLE:
 * Performs a BT terminal example by processing all data from a connected BT device 
 * and sending back an adequate response messages.
 *
 * ## Additional Function
 * - static void ninab416_clear_app_buf ( void )
 * - static void ninab416_log_app_buf ( void )
 * - static err_t ninab416_process ( ninab416_t *ctx )
 * - static err_t ninab416_read_response ( ninab416_t *ctx, uint8_t *rsp )
 * - static err_t ninab416_power_up ( ninab416_t *ctx )
 * - static err_t ninab416_example ( ninab416_t *ctx )
 *
 * @note
 * We have used the Serial Bluetooth Terminal smartphone application for the test. 
 * A smartphone and the Click board must be paired to exchange messages.
 *
 * @author Stefan Filipovic
 *
 */

#include "board.h"
#include "log.h"
#include "ninab416.h"

// Message content
#define MESSAGE_CONTENT         "NINA-B416 Click board - demo example."

static ninab416_t ninab416;
static log_t logger;

// Application buffer size
#define APP_BUFFER_SIZE         600
#define PROCESS_BUFFER_SIZE     200

static uint8_t app_buf[ APP_BUFFER_SIZE ] = { 0 };
static int32_t app_buf_len = 0;

/**
 * @brief Example states.
 * @details Predefined enum values for application example state.
 */
typedef enum
{
    NINAB416_POWER_UP = 1,
    NINAB416_EXAMPLE

} ninab416_app_state_t;

static ninab416_app_state_t app_state = NINAB416_POWER_UP;

/**
 * @brief NINA-B416 clearing application buffer.
 * @details This function clears memory of application buffer and reset its length.
 * @note None.
 */
static void ninab416_clear_app_buf ( void );

/**
 * @brief NINA-B416 log application buffer.
 * @details This function logs data from application buffer to USB UART.
 * @note None.
 */
static void ninab416_log_app_buf ( void );

/**
 * @brief NINA-B416 data reading function.
 * @details This function reads data from device and concatenates data to application buffer. 
 * @param[in] ctx : Click context object.
 * See #ninab416_t object definition for detailed explanation.
 * @return @li @c  0 - Read some data.
 *         @li @c -1 - Nothing is read.
 * See #err_t definition for detailed explanation.
 * @note None.
 */
static err_t ninab416_process ( ninab416_t *ctx );

/**
 * @brief NINA-B416 read response function.
 * @details This function waits for a response message, reads and displays it on the USB UART.
 * @param[in] ctx : Click context object.
 * See #ninab416_t object definition for detailed explanation.
 * @param[in] rsp  Expected response.
 * @return @li @c  0 - OK response.
 *         @li @c -2 - Timeout error.
 *         @li @c -3 - Command error.
 * See #err_t definition for detailed explanation.
 * @note None.
 */
static err_t ninab416_read_response ( ninab416_t *ctx, uint8_t *rsp );

/**
 * @brief NINA-B416 power up function.
 * @details This function powers up the device, performs a factory reset and reads system information.
 * @param[in] ctx : Click context object.
 * See #ninab416_t object definition for detailed explanation.
 * @return @li @c    0 - OK.
 *         @li @c != 0 - Read response error.
 * See #err_t definition for detailed explanation.
 * @note None.
 */
static err_t ninab416_power_up ( ninab416_t *ctx );

/**
 * @brief NINA-B416 example function.
 * @details This function performs a BT terminal example by processing all data from
 * a connected BT device and sending back an adequate response messages.
 * @param[in] ctx : Click context object.
 * See #ninab416_t object definition for detailed explanation.
 * @return @li @c    0 - OK.
 *         @li @c != 0 - Read response error.
 * See #err_t definition for detailed explanation.
 * @note None.
 */
static err_t ninab416_example ( ninab416_t *ctx );

void application_init ( void ) 
{
    log_cfg_t log_cfg;  /**< Logger config object. */
    ninab416_cfg_t ninab416_cfg;  /**< Click config object. */

    /** 
     * Logger initialization.
     * Default baud rate: 115200
     * Default log level: LOG_LEVEL_DEBUG
     * @note If USB_UART_RX and USB_UART_TX 
     * are defined as HAL_PIN_NC, you will 
     * need to define them manually for log to work. 
     * See @b LOG_MAP_USB_UART macro definition for detailed explanation.
     */
    LOG_MAP_USB_UART( log_cfg );
    log_init( &logger, &log_cfg );
    log_info( &logger, " Application Init " );

    // Click initialization.
    ninab416_cfg_setup( &ninab416_cfg );
    NINAB416_MAP_MIKROBUS( ninab416_cfg, MIKROBUS_1 );
    if ( NINAB416_OK != ninab416_init( &ninab416, &ninab416_cfg ) ) 
    {
        log_error( &logger, " Communication init." );
        for ( ; ; );
    }

    log_info( &logger, " Application Task " );

    app_state = NINAB416_POWER_UP;
    log_printf( &logger, ">>> APP STATE - POWER UP <<<\r\n\n" );
}

void application_task ( void ) 
{
    switch ( app_state )
    {
        case NINAB416_POWER_UP:
        {
            if ( NINAB416_OK == ninab416_power_up( &ninab416 ) )
            {
                app_state = NINAB416_EXAMPLE;
                log_printf( &logger, ">>> APP STATE - EXAMPLE <<<\r\n\n" );
            }
            break;
        }
        case NINAB416_EXAMPLE:
        {
            ninab416_example( &ninab416 );
            break;
        }
        default:
        {
            log_error( &logger, " APP STATE." );
            break;
        }
    }
}

int main ( void ) 
{
    /* Do not remove this line or clock might not be set correctly. */
    #ifdef PREINIT_SUPPORTED
    preinit();
    #endif
    
    application_init( );
    
    for ( ; ; ) 
    {
        application_task( );
    }

    return 0;
}

static void ninab416_clear_app_buf ( void ) 
{
    memset( app_buf, 0, app_buf_len );
    app_buf_len = 0;
}

static void ninab416_log_app_buf ( void )
{
    for ( int32_t buf_cnt = 0; buf_cnt < app_buf_len; buf_cnt++ )
    {
        log_printf( &logger, "%c", app_buf[ buf_cnt ] );
    }
}

static err_t ninab416_process ( ninab416_t *ctx ) 
{
    uint8_t rx_buf[ PROCESS_BUFFER_SIZE ] = { 0 };
    int32_t overflow_bytes = 0;
    int32_t rx_cnt = 0;
    int32_t rx_size = ninab416_generic_read( ctx, rx_buf, PROCESS_BUFFER_SIZE );
    if ( ( rx_size > 0 ) && ( rx_size <= APP_BUFFER_SIZE ) ) 
    {
        if ( ( app_buf_len + rx_size ) > APP_BUFFER_SIZE ) 
        {
            overflow_bytes = ( app_buf_len + rx_size ) - APP_BUFFER_SIZE;
            app_buf_len = APP_BUFFER_SIZE - rx_size;
            memmove ( app_buf, &app_buf[ overflow_bytes ], app_buf_len );
            memset ( &app_buf[ app_buf_len ], 0, overflow_bytes );
        }
        for ( rx_cnt = 0; rx_cnt < rx_size; rx_cnt++ ) 
        {
            if ( rx_buf[ rx_cnt ] ) 
            {
                app_buf[ app_buf_len++ ] = rx_buf[ rx_cnt ];
            }
        }
        return NINAB416_OK;
    }
    return NINAB416_ERROR;
}

static err_t ninab416_read_response ( ninab416_t *ctx, uint8_t *rsp ) 
{
    #define READ_RESPONSE_TIMEOUT_MS 120000
    uint32_t timeout_cnt = 0;
    ninab416_clear_app_buf ( );
    ninab416_process( ctx );
    while ( ( 0 == strstr( app_buf, rsp ) ) &&
            ( 0 == strstr( app_buf, NINAB416_RSP_ERROR ) ) )
    {
        ninab416_process( ctx );
        if ( timeout_cnt++ > READ_RESPONSE_TIMEOUT_MS )
        {
            ninab416_log_app_buf( );
            ninab416_clear_app_buf( );
            log_error( &logger, " Timeout!" );
            return NINAB416_ERROR_TIMEOUT;
        }
        Delay_ms ( 1 );
    }
    Delay_ms ( 200 );
    ninab416_process( ctx );
    ninab416_log_app_buf( );
    if ( strstr( app_buf, rsp ) )
    {
        log_printf( &logger, "--------------------------------\r\n" );
        return NINAB416_OK;
    }
    return NINAB416_ERROR_CMD;
}

static err_t ninab416_power_up ( ninab416_t *ctx )
{
    err_t error_flag = NINAB416_OK;

    log_printf( &logger, ">>> Perform device hardware reset.\r\n" );
    ninab416_reset_device ( ctx );
    error_flag |= ninab416_read_response( ctx, NINAB416_URC_GREETING );
    
    log_printf( &logger, ">>> Check communication.\r\n" );
    ninab416_cmd_run( ctx, NINAB416_CMD_AT );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );

    log_printf( &logger, ">>> Reset to factory settings.\r\n" );
    ninab416_cmd_run( ctx, NINAB416_CMD_FACTORY_RESET );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );
    
    log_printf( &logger, ">>> Reboot device.\r\n" );
    ninab416_cmd_run( ctx, NINAB416_CMD_REBOOT_DEVICE );
    error_flag |= ninab416_read_response( ctx, NINAB416_URC_GREETING );

    log_printf( &logger, ">>> Get device software version ID.\r\n" );
    ninab416_cmd_run( ctx, NINAB416_CMD_GET_SW_VERSION );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );

    log_printf( &logger, ">>> Get BT local name.\r\n" );
    ninab416_cmd_get( ctx, NINAB416_CMD_BT_LOCAL_NAME );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );

    return error_flag;
}

static err_t ninab416_example ( ninab416_t *ctx )
{
    err_t error_flag = NINAB416_OK;
    uint8_t * __generic_ptr urc_buf_ptr = 0;
    uint8_t bt_peer_handle[ 2 ] = { 0 };
    uint32_t timeout_cnt = 0;

    #define BT_TERMINAL_TIMEOUT_MS      60000
    #define BT_TERMINAL_MESSAGE_FREQ_MS 5000
    #define TERMINATION_CMD             "END"
    #define TERMINATION_RESPONSE        "Acknowledged, the connection will be terminated in a few seconds."
    #define TERMINATION_TIMEOUT         "Timeout, closing the connection in a few seconds."
    #define NEW_LINE_STRING             "\r\n"

    log_printf( &logger, ">>> Waiting for a BT peer to establish connection with the Click board...\r\n" );
    for ( ; ; )
    {
        ninab416_clear_app_buf( );
        if ( NINAB416_OK == ninab416_process( ctx ) )
        {
            Delay_ms ( 200 );
            ninab416_process( ctx );
            ninab416_log_app_buf( );
            if ( strstr( app_buf, NINAB416_URC_PEER_CONNECTED ) )
            {
                log_printf( &logger, "--------------------------------\r\n" );
                log_printf( &logger, ">>> BT peer has connected.\r\n" );
                break;
            }
        }
    }

    urc_buf_ptr = strstr( app_buf, NINAB416_URC_PEER_CONNECTED ) + strlen ( NINAB416_URC_PEER_CONNECTED );
    bt_peer_handle[ 0 ] = *urc_buf_ptr;

    log_printf( &logger, ">>> Entering data mode. URC and AT commands are not accepted in this mode.\r\n" );
    ninab416_cmd_run( ctx, NINAB416_CMD_ENTER_DATA_MODE );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );

    log_printf( &logger, ">>> Waiting for data (up to 60 seconds)...\r\n" );
    log_printf( &logger, ">>> Connection will be terminated if the Click receives an \"END\" string.\r\n" );
    for ( ; ; )
    {
        ninab416_clear_app_buf( );
        if ( NINAB416_OK == ninab416_process( ctx ) )
        {
            Delay_ms ( 100 );
            timeout_cnt = 0;
            ninab416_process( ctx );
            ninab416_log_app_buf( );
            if ( strstr( app_buf, TERMINATION_CMD ) )
            {
                log_printf( &logger, ">>> Terminate connection on demand.\r\n" );
                ninab416_generic_write ( ctx, TERMINATION_RESPONSE, strlen ( TERMINATION_RESPONSE ) );
                ninab416_generic_write ( ctx, NEW_LINE_STRING, strlen ( NEW_LINE_STRING ) );
                break;
            }
        }
        timeout_cnt++;
        if ( 0 == ( timeout_cnt % BT_TERMINAL_MESSAGE_FREQ_MS ) )
        {
            log_printf( &logger, ">>> Sending \"%s\" message to connected device.\r\n", ( char * ) MESSAGE_CONTENT );
            ninab416_generic_write ( ctx, MESSAGE_CONTENT, strlen ( MESSAGE_CONTENT ) );
            ninab416_generic_write ( ctx, NEW_LINE_STRING, strlen ( NEW_LINE_STRING ) );
        }
        if ( BT_TERMINAL_TIMEOUT_MS < timeout_cnt )
        {
            log_printf( &logger, ">>> Terminate connection due to 60s timeout expiration.\r\n" );
            ninab416_generic_write ( ctx, TERMINATION_TIMEOUT, strlen ( TERMINATION_TIMEOUT ) );
            ninab416_generic_write ( ctx, NEW_LINE_STRING, strlen ( NEW_LINE_STRING ) );
            break;
        }
        Delay_ms ( 1 );
    }
    log_printf( &logger, ">>> Switching back to command mode.\r\n" );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    ninab416_generic_write ( ctx, NINAB416_CMD_ENTER_CMD_MODE, strlen ( NINAB416_CMD_ENTER_CMD_MODE ) );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );
    
    log_printf( &logger, ">>> Closing BT peer connection.\r\n" );
    ninab416_cmd_set( ctx, NINAB416_CMD_CLOSE_PEER, bt_peer_handle );
    error_flag |= ninab416_read_response( ctx, NINAB416_RSP_OK );
    return error_flag;
}

// ------------------------------------------------------------------------ END

Additional Support

Resources

Love this project?

'Buy This Kit' button takes you directly to the shopping cart where you can easily add or remove products.