Having got the BLE Lightbulb peripheral example working as I wanted it to on the nRF52 development kit (PCA10040), the next step was to get my other dev kit to be the controller for it, in place of the smartphone app. NovelBits helpfully provides all the code for this on the page How to build the simplest nRF52 BLE Central (Lightbulb use case) but it is targeted at the nRF52840 and SDK 15.
Limitation of my available hardware
I only had one nRF52 dev kit and one nRF51 dev kit. As I learned previously, the nRF51 is only supported by SDK version 12, so I had the job of porting the example code down from SDK version 15 and changing it over to the smaller, M0 based chip. At the same time, the Softdevice (BTLE stack) changes from s132 to s130.
My plan was to proceed cautiously, having seen the problems previously in attempting to make many changes in one step and ending up with an uncompilable codebase.
- SDK v15 nRF52 PCA10040 S132
- SDK v12 nRF52 PCA10040 S132
- SDK v12 nRF51 PCA10028 S130
As soon as you copy the project folder into the same location in the SDK 12 folder and run my SES Include File Manager, you see that of the 133 include paths 29 are not found, so the structure of the SDK 12 folder is different from SDK 15.
Using the All To Relative Paths action cleans up the list to 103 paths but does not help with the files that are in the project but have since been moved. Even if all these are located, the different APIs used between the SDKs becomes an issue. But a bigger problem is the difference in the layout, naming and size of the sdk_config.h file between the two SDKs. Here's a pictorial representation of the differences in WinMerge:
|sdk_config.h||SDK 12||SDK 15|
|file size (kB)||83||293|
|Number of #defines||382||1147|
WinMerge counts 1582 differences, so there is no chance of matching up the two to bring any differences across. It becomes clear that this is not a good approach.
If you want to get there, I wouldn't start from here.
Use A Working Example
Being frustrated that I could not get my BLE Central to run on the nRF51, I wondered if it was even possible. So I explored the examples folder in the SDK 12 and found that there was a
ble_central folder and the simplest example within that was
ble_app_blinky_c inside the
experimental folder. This looks like it could be a solution for me because it has a PC10028 folder, but before getting too excited I had to program both boards as per the instructions and test it out. I didn't find those instructions to be too clear, but with the nRF52 running the code from
SDK12\examples\ble_peripheral\experimental_ble_app_blinky and the nRF51 running code from
SDK12\examples\ble_central\experimental\ble_app_blinky_c\pca10028\s130 (once turned into a SES project the central did indeed automatically find the peripheral and connect to it. Then the button 1 on one board controlled LED 3 on the other board, in both directions.
So at this point, we know it is possible to run a central on nRF51 with SDK 12. Let's look at the steps needed to make this run using Segger Embedded Studio.
Getting ble_app_blinky_c to work on nRF51 with SES
examples\ble_central\experimental\ble_app_blinky_c\pca10028\s130, copy arm5_no_packs folder and rename ses.
Proceed as per Getting Started with SES steps 4 to 6, and 13 to 15.
Open SES and Import Project - Import Keil MDK Project -
Use my SES Include File Manager to clean up the include files and save back to the project file.
Edit sdk_config.h to change
#define NRF_LOG_BACKEND_SERIAL_USES_RTT 1 so that you will see the message on startup about RAM start and size corrections that need to be made. These are
Conversion to Custom Service and Characteristic UUIDs
The difference between the blinky examples and the NovelBits example was that blinky uses Bluetooth standard UUIDs, as part of the ble_lbs_c in
SDK\components\ble\ble_services\ble_lbs_c and NovelBits uses custom UUIDs. We don't want to modify standard code in the SDK
components folder because this would affect all other projects which use this code, so instead make a local copy in the example folder which can then be modified.
Looking at the difference between the Nordic standard files in
ble_lbs_c and NovelBits'
led_service_client shows that what Afaneh has done is take the
ble_lbs_c as his basis rather than writing it from scratch. Although he doesn't claim anywhere that this is entirely his code, he did replace the Nordic Licence comments at the top of
led_service_client with his NovelBits MIT one in the downloaded version. However, there are several giveaways that this must be copied-and-edited code including: same function names, same order of functions, mention of LED Button Service is left in from the original where it should be changed to just LED Service.
Changes to ble_app_blinky_c to make it work as NovelBits' Lightbulb controller
Linker Section Placement
Add folder Clients to within folder
ble_app_blinky_c with files
led_service_client.c and h from the download on NovelBits' page
Modify main.c to remove
#include "ble_lbc_c.h" and add
#include "Clients/led_service_client.h". Also modify
m_target_periph_name = "BLE_Lightbulb"
Modify the project c_user_include_directories to remove
components\ble\ble_services\ble_lbs_c and remove the file from the nRF_BLE_Services folder, add a Clients folder with the
led_service_client c and h files.
Lesson: Don't attempt to port SDK 15 or 16 projects down to SDK 12, there are too many changes. Instead, find an SDK 12 project which is close to what you want and add functionality to an already working project to build it up to the SDK 15 or 16 version.