This builds on the example BlinkyADC and adds support for transmitting data over Bluetooth to be received by some other device such as a computer or a mobile phone. Download the example BLE.zip which contains a readme describing each file in the package.

What is BLE

BLE stands for Bluetooth Low Energy (BLE and sometimes referred to as Bluetooth Smart) and is a short range radio communications protocol. There are two distinct types of nodes in a BLE network. A given node can be one or the other type or in some instances can act as both.

  • Peripheral. A server in client/server terminology that has data to share with other nodes.
  • Central. A client in client/server terminology that is interested in data from certain peripherals. Typically your mobile phone or tablet would act as a central.

In addition, peripherals can be connectable or non-connectable. A connectable peripheral is one where a central can connect and establish a session with the peripheral and maybe issue instructions to it. A non-connectable peripheral operates like a beacon and can broadcast its data to any number of listening centrals.

This example is to build a simple non-connectable peripheral that constantly broadcasts a few items of information to listening centrals

  • The fixed string ‘Hello’
  • A 16 bit value representing the last sample voltage on the analog input
  • A 32 bit value representing the number of times the analog input has been sampled

Code

Unlike the previous examples, the code to add BLE support is a little too large to post here but is available in its entirety in the file BLE.cpp in the example package <SimpleBLE.zip>

In lieu of posting the code, each function in the source file BLE.cpp is listed here with a brief explanation of its purpose.

One Time Initialisation Functions

  • InitialiseBLE. This is a wrapper function that handles all the individual initialisation functions.
  • InitialiseBLEStack. This provides basic initialisation of the BLE stack (Nordic softdevice)
  • InitialiseGAP. Initialise the Generic Access Profile. This defines how BLE devices discover and connect with one another.
  • InitialiseGATT. Initialise the Generic Attribute Profile. This defines how data is exchanged between nodes.

Advertising Functions

Advertising is how BLE peripherals notify BLE centrals that they are present and how they can be communicated with.

  • InitialiseAndStartAdvertsing. This function is called by the application when it wants to update the advertising packet with new data and (re)start advertising. This calls the function InitialiseAdvertising.
  • InitialiseAdvertising. Configures advertising; What is present in the advertising packet, how frequently the packet is broadcast, how long the broadcast continues for, whether any scan response packets will be sent etc.
  • StartAdvertising. Start broadcasting advertising packets. While broadcasting, the peripheral makes itself visible to nearby centrals.
  • StopAdvertising. Stop broadcasting advertising packets. Stops broadcasting and is no longer visible to centrals.

Event Handlers

Invoked by the BLE stack (soft device) to notify the application code of BLE events.

  • OnAdvertisingEvent. Called when an advertising event occurs.
  • OnGATTEvent. Called when a GATT event occurs.
  • OnBLEEvent. Called when a general BLE event occurs. This is used primarily when a central connects to manage connection/disconnection and data flow between the two nodes.

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "nrf_delay.h"
#include "boards.h"
#include "main.h"

//
//	Main entry point
//
int main()
{	
    //
    //	Initialise the board.
    //
    nrf_gpio_cfg_output(LED_A);
	
    //
    //	Initialise logging over the SWO pin
    //
    ret_code_t retCode;
    SWOInit();
	
    //
    //	Enable ADC and immediately start a calibration
    //
    InitADC();
    StartADCCalibration();

    //
    //	Initilaise BLE
    //
    SWOPrintString("Initialise BLE");
    if((retCode = InitialiseBLE("NSD123")) != NRF_SUCCESS)
    {
	HandleAppErrorCheck(retCode,"InitialiseBLE");
    }

    //
    //	Loop forever toggling the led ON/OFF
    //
    bool setOn = true,initialiseAdvertising = true;
    uint32_t lastSampleNumber = 0;
    while (true)
    {
	//
	//  If requested, (re)initialise advertising
	//
	if(initialiseAdvertising)
	{
	    if((retCode = InitialiseAndStartAdvertising()) != NRF_SUCCESS)
	    {
		HandleAppErrorCheck(retCode,"InitialiseBLE");
	    }
	    initialiseAdvertising = false;
	}

	//
	//  Toggle the LED
	//
	if(setOn)
	{
	    nrf_gpio_pin_set(LED_A);
	}
	else
	{
	    nrf_gpio_pin_clear(LED_A);
	}
	setOn = setOn ? false : true;

	//
	//  Before going to sleep, start a sample
	//
	StartADCSample();
	nrf_delay_ms(500);
		
	//
	//  See if since StartADCSample a new sample value
        //  has become available
	//
	uint32_t currentSampleNumber;
	uint32_t currentSampleValue = GetLastADCSampleValueRaw(&currentSampleNumber);
	if(currentSampleNumber > lastSampleNumber)
	{
	    //
	    //	Sample number has changed therefore there
	    //	must be a new sample available
	    //
	    float vSample = GetLastADCSampleValueVoltage(NULL);
	    SWOPrintString("Sample[%4u]: %u.  %fV",currentSampleNumber,currentSampleValue,vSample);
	    lastSampleNumber = currentSampleNumber;
	    initialiseAdvertising = true;
	}
    }
}

Building and Flashing the Program

Any toolchain/programmer can be used for these steps. All the examples here are built using make and gcc. The binary is flashed using the Raspberry Pi networked programmer. See here for how to set up make, gcc and the Raspberry Pi networked programmer.

Building

From the terminal type:

C:\Projects\BLE> "c:\Program Files (x86)\GnuWin32\bin\make.exe" -f makefile CONFIG=Debug all

If there are no errors then the binary ble.elf should be output to the sub-folder bin\debug

Flashing the Binary to the Microcontroller

Hooking up the Programmer to the Microcontroller

See here for how to connect the programmer to the microcontroller.

Flashing

From a terminal type to flash both the softdevice (bluetooth stack) and the application code to the microcontroller:

C:\Projects\BLE> "C:\Program Files\NoSMD\SWorD\bin\SWorDProgrammer.exe" -program:C:\SDK\NordicSDK\nRF5_SDK_17.0.0_9d13099\components\softdevice\s132\hex\s132_nrf52_7.0.1_softdevice.hex,bin\debug\ble.elf -probe:rpi4programmer -pagesize:4096

Attempting to connect to rpi4programmer on 192.168.0.26::33332...

Connected to rpi4programmer on 192.168.0.26::33332...

Progress 100%
Completed with success

C:\Projects\BLE>

As with previous projects, the LED should be blinking and there should be printf like output on the SWO pin.

Testing BLE

Download an app to your smartphone or tablet. Some good options are:

  • LightBlue
  • nRF Connect
  • BLE Laboratory

In this example I am using BLE Laboratory as you can see the advertising data changing in real time. The image below shows our device NSD123 and the data it is advertising.

0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: