Overview: Getting Started with Nordic nRF52840 using Arduino IDE
In this article we will learn about Bluetooth Low Energy 5.0 & its application using Nordic nRF52840 with Arduino IDE. The nRF52840 SoC is a flexible, efficient Bluetooth 5 designed and developed by Nordic Semiconductor. The nRF52840 SoC is built around a 32-bit ARM® Cortex®-M4F processor optimized for ultra-low power operation. It has protocol support for Bluetooth 5, Bluetooth mesh, ANT and 2.4 GHz proprietary stacks.
The NRF52840 BLE 5.0 has a wide range of applications like Mesh Networking, For example, switching off an entire building of lights from a single smartphone. Similarly, it is used in healthcare applications like BPM, SP02, Thermometer & others. The other areas of applications include Fitness & Sports area for Athletes, Internet Connectivity, Generic sensors, HID connectivity over GATT Profiles, Proximity Sensing, audio hardware, Alert System, wireless keyboards, mice, and game controllers.
In this getting started tutorial, we will program the NRF52832 Development Board from Makerfabs. We will learn all about the GPIO Pins, architecture & Pin Mapping. We will also lear about the Bluefruit App from Adafruit. Using the Bluefruit App, we can control various devices through a wireless connectivity between Android App & NRF52840 Board.
What is Bluetooth Low Energy (BLE 5.0)?
Bluetooth 5.0 is the latest version of the Bluetooth wireless communication standard. Bluetooth 5 is the most significant advancement in the Bluetooth standard since the introduction of Bluetooth Low Energy in Bluetooth 4.0. It’s commonly used for wireless headphones and other audio hardware, as well as wireless keyboards, mice, and game controllers. Bluetooth is also used for communication between various smart home and Internet of Things (IoT) devices.
There are four significant new features of Bluetooth 5 compared to BLE 4.0:
1. A higher bit rate of 2 Mbps.
2. A long-range mode with better sensitivity at two new lower bit rates of 500 kbps and 125 kbps.
3. An 8 x improvement in broadcast capability with advertising extensions.
4. An improved channel selection algorithm
BLE 5.0 Terms
1. Central
The Central is the host computer that is often a mobile device such as a phone or tablet, or maybe desktop or laptop.
2. Peripheral
The Peripheral is the connected devices such as heart rate monitor, smartwatch, or fitness tracker.
3. Advertising
The term Advertising means the information sent by the peripheral during connection set up. When a device advertises, it is transmitting the name of the device and describing its capabilities. The central looks for advertising peripheral to connect to, and uses that information to determine what the peripheral is capable of.
4. Service
It is the function that peripheral device provides. The peripheral advertises its services. A really common service that we use is the UART service, which acts like a hardware UART and is a way of bidirectionally sending information to and from devices.
5. Packet
The data transmitted by a device is called a Packet. BLE devices and host computers transmit and receive data in small bursts called packets.
Nordic nRF52840 System on Chip
The nRF52840 System on Chip is built around a 32-bit ARM® Cortex®-M4F processor optimized for ultra-low power operation, combining Bluetooth 5, Bluetooth Mesh, Thread, IEEE 802.15.4, ANT and 2.4GHz proprietary. It is also featured with an on-chip NFC-A tag and an on-chip USB 2.0 (Full speed) controller. The SoC is developed with 1 MB FLASH and 256 kB RAM.
Features & Specifications
1. Advanced Single-chip 2.4 GHz multi-protocol SoC
2. 32-bit ARM Cortex-M4F Processor
3. 1.7v to 5.5v operation
4. 1MB flash + 256kB RAM
5. Support for long-range and high throughput
6. 802.15.4 radio Support
7. On-chip NFC
8. PPI –Programmable Peripheral Interconnect
9. Automated power management system
10. Configurable Analog/Digital I/O mapping
11. 48 GPIO, 1 QSPI, 4 SPI, 2 I2C, I²S, 2 UART, 4 PWM
12. USB 2.0 controller
13. Digital microphone interface (PDM)
14. Quadrature decoder
15. 12-bit ADC
16. Low power comparator
17. On-air compatible with nRF52, nRF51 & nRF24 Series
To learn more about the features and specification of the NRF52840 Chip, you can follow the following Datasheet: nRF52840 Datasheet
Nordic nRF52840 Development Board
There are various manufacturer of Nordic nRF52840 Development Board. The board are usually programmed using Segger Embedded Studio. But some of the boards do have support for CircuitPython & Arduino IDE. In this guide we will program nRF52840 Development Board using Arduino IDE.
Now we need to select a board to get started. There are multiple boards available in the market from different vendors as shown in the image below.
Most of the boards shown in the image are quite expensive and range from 30$ price to 70$. So I selected the best board which can be purchased at a reasonable price. The criteria for selection is that the board should have all the best features of nRF52840 Chip. The board should support CircuitPython as well as Arduino IDE. The board should also have support for various Bootloaders.
So I selected MakePython nRF52840 board from Makerfabs whcih costs only 20$. The board has an additional 1.3″ I2C OLED Display which is an extra advantage for begineers like us. The MakePython nRF52840 Board supports both Arduino & Python Code.
You can purchase this board from this link: MakePython nRF52840 Board
MakePython nRF52840 Board
MakePython nRF52840 is a powerful, generic BLE MCU module target to CircuitPython/MicroPython learners & developers. It is true “breadboard compatible”, with the very detailed pins explanation, it is easy to learn& use.
This MakePython nRF52840 leads out all pins of Nordic nRF52840, programmed with CircuitPython by default, users can begin the CircuitPython developing as getting them on hand. It is also compatible with the Arduino making it easy to get started if the correct bootloader downloaded.
Let us learn about the MakePython nRF52840 Pins. The board has 20 Outer Left PIN, 8 Inner Left PIN, 12 Outer Right PIN & 9 Inner Right PIN. The SSD1306/SSD1315 OLED Display SDA & SCL Pin is Pin P0.26 and P0.27 on the board. The onboard LED is at Pin. The board has 2 micro-USB Port. The top side of board(OLED side) MicroUSB is USB 2.0 port and the bottom side of board USB-to-UART(CP2102) port.
Getting Started with Nordic nRF52840 using Arduino IDE
So thats all about the Hardware Part. Now let’t move to the Programming Part and Program nRF52840 using Arduino IDE. The best part about this board is, the board is having Pre-installed “CircuitPython Bootloader” as well as “Arduino Bootloader“.
If you want to learn how to flash Arduino bootloader to nRF52840 Board you can follow the following Guide below.
Downloading Arduino Bootloader to nRF52840 Board
Note: Skip this Step, if you are using the same nRF52840 Development Board, i.e MakePython nRF52840
In order to download Firmware to nRF52840 Board, you need to have a J-Link. If you don’t have J-Link then you can purchase it from the following link: https://amzn.to/3hRdvz7
These steps show how to download the Arduino firmware if you had an nrf52840 board not supported by Arduino Firmware.
Step 1: Download J-Link from the following Link: https://www.segger.com/downloads/jlink/JLink_Windows.exe
Step 2: Make the following connection between J-Link Connector & nRF52840 Board.
Step 3: Open J-Flash and select “Create a new Project“. Then Click on “Start J-Flash“.
On the new window Select “Cortex-M0 Board“. Select SWD for Interface & Speed at 4000. And click OK.
Step 5: Download nRF52840 Arduino Firmware from following Link: nRF5840 Arduino Bootloader
Step 6: Power the Board using MicroUSB Port. Open the file and select the firmware you just downloaded.
Step 7: Now Click on Target. Click on “Connect“. This will connect the Board with J-Link. Then Select Manual Programming. First Erase the chip by clicking on “Erase Chip“. Once the Chip is Erased, you can now program the device by clicking on “Program & Verify” option.
You have successfully flashed Arduino Bootloader to nrF52840 Development Board.
Adding nRF52840 to Board Manager of Arduino IDE
Now we need to install Boards to the Arduino IDE. So follow the following steps:
Step 1: Open your Arduino IDE. Click on File >>> Preference
Step 2: Copy the following Board Manager Url to the “Additional Board Manager URLs” Section. And after adding Click on OK.
|
1 |
https://adafruit.github.io/arduino-board-index/package_adafruit_index.json |
Step 3: Now Go to Tools >>>> Boards >>>> Board Manager
Step 4: Now Search for NRF52840 in the Search Box.
So select nrf52 Adafruit Option & click on install. So after a while, the board will be successfully installed.
nRF52840 Arduino 1st Program – Blinking of LED
Now let us test the board by writing an LED Blink Code. This simple code is like writing the “Hello World” Command in the C program. This program will help you to know whether the Board is working or not. This also verifies whether the Bootloader is uploaded & working.
So take an LED of any color and connect the LED Positive Pin to P0.30 of MakePython nRF52840 Board. Connect the LED negative pin to GND.
Here is a Simple Arduino Code. Copy the following Arduino Code and Paste it in the Arduino IDE window.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#define LED_BUILTIN 30 // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } |
Now compile the code. After compiling, Select the following Board and Port & Click on Upload. You can upload the code to nRF52840 Board using any of the USB Port, as it has 2 USB Ports. The CP2102 Driver needs to be installed on your PC in order to show the Port.
So the after the code is uploaded successfully the LED will start blinking. You can change the blink interval to check more. You can also try the same code with some other Input/Output Pins.
Well that’s all about nRF52840 Arduino Getting Started Tutorial. Now let us move to the main part of the nRF52840 chip, i.e. Wireless Communication Part.
Adafruit Bluefruit LE Connect App
To interact with your board from your phone or tablet, you’ll use the Adafruit Bluefruit LE Connect App. Download or Simply Install the App from Apple App Store or Google Play App Store
This App only works if you have code running on nRF52840 Development Board. The device will only advertise when the code is running. The means the device will transmit/show the device name on Android/Apple Phone if the device is running.
So now lets run code on the board and check the working.
Arduino Code/Program to Communicate with Bluefruit LE Connect App
First we need to install “Bluefruit App Library” to the Arduino IDE. The Bluefruit App is supported by Adafruit_BusIO Library.
Since we are using OLED Display to display the events happening. So we need to install Libraries for OLED Display. Download the following Library and add it to the Library Folder.
Now open a New Sketch in your Arduino IDE and copy the following code as shown below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
#include <bluefruit.h> #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // OTA DFU service BLEDfu bledfu; // Uart over BLE service BLEUart bleuart; // Function prototypes for packetparser.cpp uint8_t readPacket (BLEUart *ble_uart, uint16_t timeout); float parsefloat (uint8_t *buffer); void printHex (const uint8_t * data, const uint32_t numBytes); // Packet buffer extern uint8_t packetbuffer[]; void setup(void) { // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D/0x3C for 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;) // Don't proceed, loop forever { Serial.println("Now Loop!"); delay(500); } } Serial.println(F("SSD1306 init success")); display.clearDisplay(); Serial.begin(115200); while ( !Serial ) delay(10); // for nrf52840 with native usb Serial.println(F("Adafruit Bluefruit52 Controller App Example")); Serial.println(F("-------------------------------------------")); display.clearDisplay(); display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Bluefruit52"); display.setCursor(0,30); display.print("Controller"); display.display(); Bluefruit.begin(); Bluefruit.setTxPower(4); // Check bluefruit.h for supported values Bluefruit.setName("Bluefruit52"); // To be consistent OTA DFU should be added first if it exists bledfu.begin(); // Configure and start the BLE Uart service bleuart.begin(); // Set up and start advertising startAdv(); Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode")); Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!")); Serial.println(); display.clearDisplay(); display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Activate"); display.setCursor(0,30); display.print("Controls"); display.display(); } void startAdv(void) { // Advertising packet Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); Bluefruit.Advertising.addTxPower(); // Include the BLE UART (AKA 'NUS') 128-bit UUID Bluefruit.Advertising.addService(bleuart); // Secondary Scan Response packet (optional) // Since there is no room for 'Name' in Advertising packet Bluefruit.ScanResponse.addName(); /* Start Advertising * - Enable auto advertising if disconnected * - Interval: fast mode = 20 ms, slow mode = 152.5 ms * - Timeout for fast mode is 30 seconds * - Start(timeout) with timeout = 0 will advertise forever (until connected) * * For recommended advertising interval * https://developer.apple.com/library/content/qa/qa1931/_index.html */ Bluefruit.Advertising.restartOnDisconnect(true); Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Wait for new data to arrive uint8_t len = readPacket(&bleuart, 500); if (len == 0) return; // Got a packet! // printHex(packetbuffer, len); // Color if (packetbuffer[1] == 'C') { uint8_t red = packetbuffer[2]; uint8_t green = packetbuffer[3]; uint8_t blue = packetbuffer[4]; Serial.print ("RGB #"); if (red < 0x10) Serial.print("0"); Serial.print(red, HEX); if (green < 0x10) Serial.print("0"); Serial.print(green, HEX); if (blue < 0x10) Serial.print("0"); Serial.println(blue, HEX); display.clearDisplay(); display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("RGB Color"); display.setCursor(10,30); display.print("#"); display.print(red, HEX); display.print(green, HEX); display.println(blue, HEX); display.display(); } // Buttons if (packetbuffer[1] == 'B') { uint8_t buttnum = packetbuffer[2] - '0'; boolean pressed = packetbuffer[3] - '0'; Serial.print ("Button "); Serial.print(buttnum); if (pressed) { Serial.println(" pressed"); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Button Status"); display.setCursor(0,20); display.print("pressed "); display.print(buttnum); display.display(); } else { Serial.println(" released"); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Button Status"); display.setCursor(0,20); display.print("Released "); display.print(buttnum); display.display(); } } // GPS Location if (packetbuffer[1] == 'L') { float lat, lon, alt; lat = parsefloat(packetbuffer+2); lon = parsefloat(packetbuffer+6); alt = parsefloat(packetbuffer+10); Serial.print("GPS Location\t"); Serial.print("Lat: "); Serial.print(lat, 4); // 4 digits of precision! Serial.print('\t'); Serial.print("Lon: "); Serial.print(lon, 4); // 4 digits of precision! Serial.print('\t'); Serial.print(alt, 4); Serial.println(" meters"); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("GPS Location"); display.setCursor(0,20); display.print("Lat:"); display.print(lat, 4); display.setCursor(0,30); display.print("Lon:"); display.print(lon, 4); display.setCursor(0,40); display.print("Alt:"); display.print(alt, 4); display.display(); } // Accelerometer if (packetbuffer[1] == 'A') { float x, y, z; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); Serial.print("Accel\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.println(); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Accelerometer"); display.setCursor(0,20); display.print("X: "); display.print(x); display.setCursor(0,30); display.print("Y: "); display.print(y); display.setCursor(0,40); display.print("Z: "); display.print(z); display.display(); } // Magnetometer if (packetbuffer[1] == 'M') { float x, y, z; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); Serial.print("Mag\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.println(); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Magnetometer"); display.setCursor(0,20); display.print("X: "); display.print(x); display.setCursor(0,30); display.print("Y: "); display.print(y); display.setCursor(0,40); display.print("Z: "); display.print(z); display.display(); } // Gyroscope if (packetbuffer[1] == 'G') { float x, y, z; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); Serial.print("Gyro\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.println(); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Gyroscope"); display.setCursor(0,20); display.print("X: "); display.print(x); display.setCursor(0,30); display.print("Y: "); display.print(y); display.setCursor(0,40); display.print("Z: "); display.print(z); display.display(); } // Quaternions if (packetbuffer[1] == 'Q') { float x, y, z, w; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); w = parsefloat(packetbuffer+14); Serial.print("Quat\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.print('\t'); Serial.print(w); Serial.println(); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print("Quaternions"); display.setCursor(0,20); display.print("X: "); display.print(x); display.setCursor(0,30); display.print("Y: "); display.print(y); display.setCursor(0,40); display.print("Z: "); display.print(z); display.setCursor(0,50); display.print("W: "); display.print(w); display.display(); } } |
Similarly open another Tab on the Arduino IDE and paste the following code below. Save the file with the name “packetParser.cpp” as shown in the image below.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
#include <string.h> #include <Arduino.h> #include <bluefruit.h> #define PACKET_ACC_LEN (15) #define PACKET_GYRO_LEN (15) #define PACKET_MAG_LEN (15) #define PACKET_QUAT_LEN (19) #define PACKET_BUTTON_LEN (5) #define PACKET_COLOR_LEN (6) #define PACKET_LOCATION_LEN (15) // READ_BUFSIZE Size of the read buffer for incoming packets #define READ_BUFSIZE (20) /* Buffer to hold incoming characters */ uint8_t packetbuffer[READ_BUFSIZE+1]; /**************************************************************************/ /*! @brief Casts the four bytes at the specified address to a float */ /**************************************************************************/ float parsefloat(uint8_t *buffer) { float f; memcpy(&f, buffer, 4); return f; } /**************************************************************************/ /*! @brief Prints a hexadecimal value in plain characters @param data Pointer to the byte data @param numBytes Data length in bytes */ /**************************************************************************/ void printHex(const uint8_t * data, const uint32_t numBytes) { uint32_t szPos; for (szPos=0; szPos < numBytes; szPos++) { Serial.print(F("0x")); // Append leading 0 for small values if (data[szPos] <= 0xF) { Serial.print(F("0")); Serial.print(data[szPos] & 0xf, HEX); } else { Serial.print(data[szPos] & 0xff, HEX); } // Add a trailing space if appropriate if ((numBytes > 1) && (szPos != numBytes - 1)) { Serial.print(F(" ")); } } Serial.println(); } /**************************************************************************/ /*! @brief Waits for incoming data and parses it */ /**************************************************************************/ uint8_t readPacket(BLEUart *ble_uart, uint16_t timeout) { uint16_t origtimeout = timeout, replyidx = 0; memset(packetbuffer, 0, READ_BUFSIZE); while (timeout--) { if (replyidx >= 20) break; if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN)) break; if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN)) break; if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN)) break; if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN)) break; if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN)) break; if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN)) break; if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN)) break; while (ble_uart->available()) { char c = ble_uart->read(); if (c == '!') { replyidx = 0; } packetbuffer[replyidx] = c; replyidx++; timeout = origtimeout; } if (timeout == 0) break; delay(1); } packetbuffer[replyidx] = 0; // null term if (!replyidx) // no data or timeout return 0; if (packetbuffer[0] != '!') // doesn't start with '!' packet beginning return 0; // check checksum! uint8_t xsum = 0; uint8_t checksum = packetbuffer[replyidx-1]; for (uint8_t i=0; i<replyidx-1; i++) { xsum += packetbuffer[i]; } xsum = ~xsum; // Throw an error message if the checksum's don't match if (xsum != checksum) { Serial.print("Checksum mismatch in packet : "); printHex(packetbuffer, replyidx+1); return 0; } // checksum passed! return replyidx; } |
Communication Between nRF52840 Adafruit Bluefruit LE Connect App
Compile the above sketch and flash it to your nRF52840 Devleopment Board. Once you are done uploading, open the Serial Monitor (Tools > Serial Monitor). The Serial Monitor will show the following output.
Now Open the Bluefruit LE Connect application on your mobile device. Connect to the appropriate target ‘Bluefruit52‘.
Once connected switch to the Controller application inside the app.
Now you can Enable an appropriate control surface. The following are the controls as shown in the image below.
Now you can check the control of each function. The Accelerometer, Gyroscope, Magnetometer, Color Picker, etc can be enabled and disabled by turning the ON/OFF virtual button. The SSD1306 I2C OLED Display will display the data obtained from your Phone.
Video Tutorial & Explanation
So, that’s all from nRF52840 Development Board Arduino Tutorial. In some other Tutorial, you will see more projects using BLE 5.0 Chips. If you have any doubts or queries, you can comment down below. All the suggestions are appreciated.
You can check another BLE 5.0 version here from Texas Instrument: Reyax RYB080I.






































5 Comments
Hey! I watched your video on youtube and you have a great tutorial. I am currently using the adafruit itsy bitsy nRF52840 using the Arduino IDE and i am a beginner. Ive gotten through the arduino examples on the adafruit website but am looking to do some coding one step further. I am wondering if you have any tutorials or articles on specifically advertising the microcontroller to the phone (through nrf connect or another bluetooth app) while being able to package and send data from an external sensor like a hall effect sensor reading rpm
Hi Mitchell thank you for the comment. Meanwhile, I don’t have any such tutorial but I will be making the tutorial very soon.
Hi.
I am beginner developer, what is the format for Firmware? .Bin?
thanks and regards
Hey Mitchell, did you find any other sources? I am using the itsybitsy too and would like to send sensor data to an app or computer using bluetooth
Hi, I am using itsybitsy nrf52840. Is it possible if I want to send collected data from one of the pins of the board to the Bluefruit app using BLE? If so, may I have the instruction for coding?