BLE pairing

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

BLE pairing

Jump to solution
4,982 Views
syed_idris
Contributor III

Hi,

We are using USB-KW40 with IAR, and able to do "WIreless UART" code which is communicating with "Kinetis BLE Toolbox", But what should we do to send "Hello Word \n" from USB-KW40 to our cell phone bluetooth? We can see the device name on our cell phone but not able to pair with bluetooth.

Labels (1)
Tags (2)
0 Kudos
Reply
1 Solution
3,426 Views
isaacavila
NXP Employee
NXP Employee

Hello Syed,

I will try to explain how wireless_uart is structured. In function BleApp_StateMachineHandler function, different event states are handled, at the begining, mAppIdle_c state is handled, in this function a software timer is started:

TMR_StartLowPowerTimer(mUartStreamFlushTimerId,

                gTmrLowPowerIntervalMillisTimer_c,

                15,

                UartStreamFlushTimerCallback, NULL); 

This timer is configured to call UartStreamFlushTimerCallback callback every 15 milliseconds (and this callback is used to read from console and send it back to cellphone). Once timer is running, application continues with its logic (Find art stream characteristics and store service handles) until it is in mAppRunning_c state.

As callback is called every 15 millisenconds, UartStreamFlushTimerCAllback will be polling for data in serial port just after application is in mAppRunning_c state. So this UartStreamFlushTimerCallback is called periodically.

If you want to send data to Wireless Uart application only once you have to consider:

  • Buetooth state machine is in mAppRunning_c state in order to call BleApp_SendUartStream function.
  • Data to be send must terminate in '0x0D'.

I added a short workaround that prints a message in th terminal:

#if WORKAROUND_TO_SEND_DATA_ONCE

static uint8_t message_was_sent = FALSE;

uint8_t data_buffer[] = {"This is my test\r"};

#endif

static void UartStreamFlushTimerCallback(void *pData)

{

    uint16_t        bytesRead = 0;

    uint16_t        byteCount = 0;

   

    if (mPeerInformation.appState != mAppRunning_c)

    {

        return;

    }  

#if WORKAROUND_TO_SEND_DATA_ONCE

    if (!message_was_sent) {

        message_was_sent = TRUE;

        /* Send data to app, buffer size is decreased by one in order to eliminate NULL character at the buffer's end and last byte could be 0x0D*/

        BleApp_SendUartStream(mPeerInformation.deviceId, &data_buffer[0], sizeof(data_buffer) - 1);

    } else {

#endif

      if ( Serial_Read( gAppSerMgrIf, recvStream, mAppUartBufferSize_c, &bytesRead) == gSerial_Success_c )

      {

          while (byteCount < bytesRead)

          {

              BleApp_SendUartStream(mPeerInformation.deviceId, &recvStream[byteCount], MIN(mUartStreamMaxSize_c, bytesRead - byteCount));

              byteCount += MIN(mUartStreamMaxSize_c, bytesRead - byteCount);

          }

      }

#if WORKAROUND_TO_SEND_DATA_ONCE

    }

#endif

}

In this workaround, message will be printed only once due message_was_sent boolean variable, so, although this UartStreamFlushTimerCallback function is called periodically, it will only send data_buffer the first time.

Another possible solution could be to start an One shot timer and use the callback to send this data to application, this way you do not need to use a boolean variable to control if message has been sent. This solution would look like:

static tmrTimerID_t mOneShotTimerId;

In BleApp_Config function, add the last line:

/* Allocate application timer */

    mAppTimerId = TMR_AllocateTimer();

    mUartStreamFlushTimerId = TMR_AllocateTimer();

    mBatteryMeasurementTimerId = TMR_AllocateTimer();

    mOneShotTimerId = TMR_AllocateTimer();

And start this timer just before application reaches mAppRunning_c state:

case mAppCharServiceDisc_c:

    {

        if (event == mAppEvt_GattProcComplete_c)

        {

            /* Moving to Running State*/

            mPeerInformation.appState = mAppRunning_c;

           

            mpServiceDiscoveryBuffer->aCharacteristics = mpCharDiscoveryBuffer;

             

            BleApp_StoreServiceHandles(mpServiceDiscoveryBuffer);

            BleApp_ServiceDiscoveryReset();

           TMR_StartLowPowerTimer(mOneShotTimerId,

                gTmrLowPowerSingleShotMillisTimer_c,

                500,

                myCallbackToSendDataOnce, NULL);

        }

So 500 milliseconds after mAppRunning_c state is reached, myCallbackToSendDataOnce function will be called and in this callback you can send data to cellphone, just remember to end this buffer by using 0x0D.

Does it make sense to you?

Hope this helps,

Regards,

Isaac

View solution in original post

9 Replies
3,426 Views
miguel_reyes
NXP Employee
NXP Employee

Where are you calling BleApp_SendUartStream()? did you check that you are not calling this periodically? Inside of a timer callback or event?

It should be sending the write command once.

0 Kudos
Reply
3,426 Views
syed_idris
Contributor III

yes it is called in timer callback function.

UartStreamFlushTimerCallback(void *pData)

then where should it be called to print "hello world" only one time?

0 Kudos
Reply
3,427 Views
isaacavila
NXP Employee
NXP Employee

Hello Syed,

I will try to explain how wireless_uart is structured. In function BleApp_StateMachineHandler function, different event states are handled, at the begining, mAppIdle_c state is handled, in this function a software timer is started:

TMR_StartLowPowerTimer(mUartStreamFlushTimerId,

                gTmrLowPowerIntervalMillisTimer_c,

                15,

                UartStreamFlushTimerCallback, NULL); 

This timer is configured to call UartStreamFlushTimerCallback callback every 15 milliseconds (and this callback is used to read from console and send it back to cellphone). Once timer is running, application continues with its logic (Find art stream characteristics and store service handles) until it is in mAppRunning_c state.

As callback is called every 15 millisenconds, UartStreamFlushTimerCAllback will be polling for data in serial port just after application is in mAppRunning_c state. So this UartStreamFlushTimerCallback is called periodically.

If you want to send data to Wireless Uart application only once you have to consider:

  • Buetooth state machine is in mAppRunning_c state in order to call BleApp_SendUartStream function.
  • Data to be send must terminate in '0x0D'.

I added a short workaround that prints a message in th terminal:

#if WORKAROUND_TO_SEND_DATA_ONCE

static uint8_t message_was_sent = FALSE;

uint8_t data_buffer[] = {"This is my test\r"};

#endif

static void UartStreamFlushTimerCallback(void *pData)

{

    uint16_t        bytesRead = 0;

    uint16_t        byteCount = 0;

   

    if (mPeerInformation.appState != mAppRunning_c)

    {

        return;

    }  

#if WORKAROUND_TO_SEND_DATA_ONCE

    if (!message_was_sent) {

        message_was_sent = TRUE;

        /* Send data to app, buffer size is decreased by one in order to eliminate NULL character at the buffer's end and last byte could be 0x0D*/

        BleApp_SendUartStream(mPeerInformation.deviceId, &data_buffer[0], sizeof(data_buffer) - 1);

    } else {

#endif

      if ( Serial_Read( gAppSerMgrIf, recvStream, mAppUartBufferSize_c, &bytesRead) == gSerial_Success_c )

      {

          while (byteCount < bytesRead)

          {

              BleApp_SendUartStream(mPeerInformation.deviceId, &recvStream[byteCount], MIN(mUartStreamMaxSize_c, bytesRead - byteCount));

              byteCount += MIN(mUartStreamMaxSize_c, bytesRead - byteCount);

          }

      }

#if WORKAROUND_TO_SEND_DATA_ONCE

    }

#endif

}

In this workaround, message will be printed only once due message_was_sent boolean variable, so, although this UartStreamFlushTimerCallback function is called periodically, it will only send data_buffer the first time.

Another possible solution could be to start an One shot timer and use the callback to send this data to application, this way you do not need to use a boolean variable to control if message has been sent. This solution would look like:

static tmrTimerID_t mOneShotTimerId;

In BleApp_Config function, add the last line:

/* Allocate application timer */

    mAppTimerId = TMR_AllocateTimer();

    mUartStreamFlushTimerId = TMR_AllocateTimer();

    mBatteryMeasurementTimerId = TMR_AllocateTimer();

    mOneShotTimerId = TMR_AllocateTimer();

And start this timer just before application reaches mAppRunning_c state:

case mAppCharServiceDisc_c:

    {

        if (event == mAppEvt_GattProcComplete_c)

        {

            /* Moving to Running State*/

            mPeerInformation.appState = mAppRunning_c;

           

            mpServiceDiscoveryBuffer->aCharacteristics = mpCharDiscoveryBuffer;

             

            BleApp_StoreServiceHandles(mpServiceDiscoveryBuffer);

            BleApp_ServiceDiscoveryReset();

           TMR_StartLowPowerTimer(mOneShotTimerId,

                gTmrLowPowerSingleShotMillisTimer_c,

                500,

                myCallbackToSendDataOnce, NULL);

        }

So 500 milliseconds after mAppRunning_c state is reached, myCallbackToSendDataOnce function will be called and in this callback you can send data to cellphone, just remember to end this buffer by using 0x0D.

Does it make sense to you?

Hope this helps,

Regards,

Isaac

3,426 Views
wenxue
NXP Employee
NXP Employee

Hi Isaac,

Do you know how KW41 to achive the same function? That is send data to MobilePhone through UART.

0 Kudos
Reply
3,426 Views
isaacavila
NXP Employee
NXP Employee

Hello Wenxue,

I've not checked KW41's BLE stack because it is still not available, but I assume that this UART application should work same as KW40's does.

Sorry for this inconvenience,

Regards,

Isaac

0 Kudos
Reply
3,426 Views
miguel_reyes
NXP Employee
NXP Employee

Wireless UART requires a PC serial terminal. Once you open a terminal using the COM enumerated by the USB-KW40Z, you can type message in the terminal, then type "Enter" and the message will be sent to the phone and it will be displayed in the Wireless UART application which is part of the Kinetis BLE Toolbox.

0 Kudos
Reply
3,426 Views
syed_idris
Contributor III

We already did this and its working good.

But

1- instead of using "Kinetis BLE toolbox" can't we use any other bluetooth terminal on our cellphones?

2- And instead of writing on PC serial terminal we want to write "Hello \n" in the code only, means as we pair with the bluetooth application it should display "Hello" on cellphone without typing in PC serial monitor.

What should we do?

0 Kudos
Reply
3,426 Views
miguel_reyes
NXP Employee
NXP Employee

Syed,

You need to create a mobile application that supports BLE communication to discover Wireless UART devices, then discover the service Wireless UART to start playing with it.

At the end, Wireless UART application has only one service which supports UART stream characteristic which is the one sent to the peer device. So, you need to fill the uart stream characteristic with the information you want.

So, in the wireless UART application you have a timer that is flushing the buffer which is passed to the uart stream attribute in the application. Please, take a look to the function BleApp_SendUartStream. It is the one that send the information to the peer device, please debug and see when this function is called. Actually this function would be called whenever you type a something into the serial terminal. If you want to send the "hello" message from the beginning, you need to change the logic of the application to send the word by the trigger event you wish. By default, this application waits to receive a serial input to trigger a message over the air.

0 Kudos
Reply
3,426 Views
syed_idris
Contributor III

Yeh..

Just made string 'hello' in array new[] and changed the BleApp_SendUartStream as below

BleApp_SendUartStream(mPeerInformation.deviceId, &new[0] ,7);

and successfully getting 'hello' on wireless UART of kinetis BLE toolbox, it has to come only once but it is coming continuously even if the the while loop is commented.

Why so?

And we still need to create BLE suppoerted android app for getting wireless UART data on mobile.

0 Kudos
Reply