BLE-UART-LCD DEMO

OBJECTIVE

Use of nRF51822 to demonstrate usage of BLE-UART service provided by Nordic and the use of uLCD-144-G2. The demonstration uses the nRF Master Control Panel and nRF UART demo apps provided by Nordic and available on Google Play Store and Apple Store.


DETAILS

The nRF51822-mKIT is a low cost ARM mbed enabled development board for Bluetooth® Smart designs with the nRF51822 SoC. Nordic Semiconductor provides a UART Service that emulates a serial port over BLE. It demonstrates the usage of proprietary (vendor specific) service and characteristics with the S110 SoftDevice (precompiled software implementing Bluetooth 4.0 low energy technology). The GATT Battery and Device Information Service are also added to the project to show the use of a proprietary service with other GATT specifications. One of the problems in the project is that we lack the Serial Debug port (USB-UART) as we use the UART lines to control the LCD. Once the LCD works with no errors, we can use the LCD as a console to print debug messages. The project does not stop advertising, so be careful to switch off the supply if using a coin-cell battery. If left ON with the firmware it may just drain all the battery.


COMPONENTS

nRF51822 mbed Kit uLCD-144-G2 mbed NXP LPC1768 (only for 5V supply)


WIRING

Power Supply connection: nRF51822 mbed Kit does not have a 5V output and gives only a 3V output. Thus, a separate 5V supply is needed for the LCD. One can also solder a wire to the USB Connector and take the 5V supply from the USB connector. The soldering can be a bit tricky though. The USB allows a maximum current consumption of 500mA after the device successfully enumerates and the LCD has a maximum current consumption of 250mA. The circuit should therefore work. For this setup, I used another mBed kit that has a power regulator to supply the 5V output. The GND of the three ICs were shorted together for consistent voltage levels.

UART connection: The LCD communicates over UART. The nRF51822-mkit has a UART connection but it connects to the Interface MCU on those lines. To disable this connection, we have two options. First, using SW4 switch (Switching it OFF) we can disconnect the UART lines of nRF51822 from the interface MCU while powering the nRF51822 over USB. Second, we can use the 2032 coin-cell battery. The UART lines are disconnected automatically when USB is not used for powering up the device. The second option of 2032 coin-cell battery was used in this setup.

Reset Pin for LCD: The LCD requires a Reset pin to reset it. A GPIO pin (P0.1) was used for this purpose. Details on mounting the uLCD-144-G2 kit on a breadboard and the pin connections can be referred to at the following link: https://developer.mbed.org/users/4180_1/notebook/ulcd-144-g2-128-by-128-color-lcd/can be referred.

uLCD-144-G2nRF51822 mbed kitNXP LPC1768 mbed kit
5V--VU(5.0v USB Out)
GNDGNDGND
TXRX (P0.11)--
RXTX(P0.09)--
ResetP0.01--

/media/uploads/garimagupta002/connections_small.jpg


DEMO CODE

main.cpp

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "BLEDevice.h"

//To use LCD
#include "uLCD_4DGL.h"

//UART Primary Service
#include "UARTService.h"

//Battery and DeviceInformation Auxilary Services
#include "BatteryService.h"
#include "DeviceInformationService.h"

BLEDevice  ble;
DigitalOut led1(LED1);
uLCD_4DGL uLCD(P0_9,P0_11,P0_1);

//Using the standard GATT Service IDs.
static const uint16_t uuid16_list[]        = {GattService::UUID_BATTERY_SERVICE,
                                              GattService::UUID_DEVICE_INFORMATION_SERVICE};
                                              
//Used to access the defined in main UARTService object globally.
UARTService *uartServicePtr;

//Keeping a receive buffer to alter the data received.
uint8_t DatatoSend[1000];

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    //Print the LCD messages.
    uLCD.cls();
    uLCD.printf("\n Disconnected.!!\n");
    uLCD.printf("\n Restarting the advertising process.");
    ble.startAdvertising();
}

void onDataWritten(const GattCharacteristicWriteCBParams *params)
{
    if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
        uint16_t bytesRead = params->len;

        uLCD.cls();
        uLCD.printf("Data Received.!!\n");
        
        for(int j=0;j<bytesRead;j++)
        {
            uLCD.printf(" %x\n",*((params->data)+j));
            DatatoSend[j]=(*((params->data)+j))+1;
        }
        wait(1);
        
        ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), DatatoSend, bytesRead);

        //Use the below statement for loopback.
        //ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead);
        
        uLCD.cls();
        uLCD.printf("Data Sent.!!\n");
        for(int j=0;j<bytesRead;j++)
        {
            uLCD.printf(" %x\n",DatatoSend[j]);
        }
        wait(1);
    }
}

void periodicCallback(void)
{
    led1 = !led1;
}

int main(void)
{
    uLCD.reset();    
    uLCD.printf("\n Hello...\n"); //Default Green on black text
    uLCD.printf("\n Starting BLE-UART Demo...");
    
    led1 = 1;
    Ticker ticker;
    ticker.attach(periodicCallback, 1);

    ble.init();
    ble.onDisconnection(disconnectionCallback);
    ble.onDataWritten(onDataWritten);

    /* Set up Primary service*/
    UARTService uartService(ble);
    uartServicePtr = &uartService;
    
    /* Setup auxiliary services. */
    BatteryService           battery(ble);
    DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");


    /* Setup advertising */
    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                     (const uint8_t *)"BLE UART", sizeof("BLE UART") - 1);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS,
                                     (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
    ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));                               
    ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
    ble.startAdvertising();
    uLCD.text_width(1);
    uLCD.text_height(1);
    uLCD.color(GREEN);
    
    uLCD.cls();
    uLCD.locate(0,2);
    uLCD.printf("Started Advertising.!! \n");
    wait(1);
        
    while (true) {
        
        uLCD.cls();
        uLCD.locate(0,2);
        uLCD.printf("\nWaiting to receive Data.\n");  
        ble.waitForEvent();
    }
}

The demo first resets the LCD. The LCD is reset implicitly every time you reset the device. But the reset API is still included to make sure that the LCD device gets reset. A 1msec timer is started to keep an LED blinking, to check if the program hangs somewhere and not blink the LED. The BLE initialization is done next and two call back functions for a Disconnection and Connection Event are initialized. The primary and auxiliary services are initialized next. Next the advertising is setup with the appropriate parameters and started. The program then waits infinitely to receive data on the TX Characteristic. As soon as the data is received, the onDataWritten API is called which reads the received data, increments it by 1 and stores it in a buffer ‘DatatoSend’. The wait(1) keeps the content on the display for 1 msec. It will otherwise clear off very quickly and not be visible. The ‘DatatoSend’ buffer data is sent over the RX Characteristic and displayed on the LCD.

Use of Android/iOS Application: The nRF UART and nRF Master Control Panel applications send data in ASCII and display the ASCII characters. Thus, you will see the ascii values of the data received on the LCD display. In the Master Control Panel App, one needs to enable the notifications for RX Characteristic to be able to see the received data. The nRF UART application takes care of this by itself. This has been demonstrated in the demo video below.

The appropriate libraries are included in the following program:

Import programBLE_UART_LCD_Batt_DevInfo

Use of nRF51822 to demonstrate usage of BLE-UART service provided by Nordic and the use of uLCD-144-G2. The demonstration uses the nRF Master Control Panel and nRF UART demo apps provided by Nordic and available on Google Play and Apple Store. The firmware receives data over the TX characteristic, increments it by 1 and sends it over RX characteristic. The notifications need to be enabled for the RX characteristic in the Master Control Panel to be able to receive the data. For more information check the notebook page: http://developer.mbed.org/users/garimagupta002/notebook/ble-uart-lcd-demo/

DEMO VIDEO


Please log in to post comments.