5.3.2 BLE and QEI Transparent UART

This section explains the process of creating a peripheral device designed to transmit Quadrature Encoder Interface (QEI) data to a Bluetooth® Low Energy (BLE) connected mobile device using Microchip's proprietary Transparent UART Profile. The peripheral device featured in this demo is the advanced PIC32WM-BZ6204UE, while the central device is a smartphone equipped with the Microchip Bluetooth Data (MBD) application.

This showcase highlights a motor sensor system that leverages the QEI to accurately capture essential motor encoder data, such as position counters and velocity metrics. Once the motor data is captured via the QEI, the PIC32WM-BZ6204UE seamlessly transmits this information to the MBD application using the Transparent UART profile, ensuring reliable and efficient data communication.

For this demonstration, we utilize a motor equipped with Hall Sensor A and Hall Sensor B outputs, making it versatile and compatible with various motor types. The specific motor used in this demo “Encoder Metal Gear motor 12V DC High Speed 130RPM Gear Motor with Encoder for Arduino and 3D Printers”.

Users can choose to either run the precompiled Application Example hex file provided on the PIC32-BZ6 Curiosity Board or follow the steps to develop the application from scratch.

It is recommended to follow the examples in sequence to understand the basic concepts before progressing to the advanced topics.

  1. Getting Started with Application Building Blocks – See Building Block Examples from Related Links.

  2. Getting Started with Peripheral Building Blocks – See Peripheral Devices from Related Links.

  3. See BLE Connection from Related Links.
  4. See BLE Transparent UART from Related Links.
  5. BLE Software Specification – See MPLAB® Harmony Wireless BLE in Reference Documentation from Related Links.

Hardware Requirement

Table 5-69. Hardware Requirement
S. No. Tool Qty
1PIC32-BZ6 Curiosity Board1
2Micro USB cable1
3Hall Encoder DC Motor1
4AC/DC Adapter1

SDK Setup

Refer to Getting Started with Software Development from Related Links.

Software Requirement

  1. To install Tera Term tool, refer to the Tera Term web page in Reference Documentation from Related Links.

Smart phone App

  1. Microchip Bluetooth® Data (MBD)

Programming the Precompiled Hex File or Application Example

Using MPLAB® X IPE:

  1. Import and program the precompiled hex file: <Harmony Content Path>\wireless_apps_pic32_bz6\apps\ble\peripheral_applications\qei_peripheral_trp_uart\precompiled_hex.
  2. For detailed steps, refer to Programming a Device in MPLAB® IPE in Reference Documentation from Related Links.
    Note: Ensure to choose the correct Device and Tool information.

Using MPLAB® X IDE:

  1. Perform the following the steps mentioned in Running a Precompiled Example. For more information, refer to Running a Precompiled Application Example from Related Links.
  2. Open and program the application “qei_peripheral_trp_uart.X” located in “<Harmony Content Path>\wireless_apps_pic32_bz6\apps\ble\ peripheral _applications\qei_peripheral_trp_uart\firmware” using MPLAB X IDE.
  3. For more details on how to find the Harmony Content Path, refer to Installing the MCC Plugin from Related Links.

Demo Description

Once the demo application is programmed, PIC32WM-BZ6204UE will begin advertising. A central device, such as a smartphone, can scan for these advertisements and connect by searching for the name “pic32cx-bz6” on the Microchip Bluetooth Data (MBD) app. Upon establishing a connection, QEI data will be transferred from PIC32WM-BZ6204UE to the MBD app via BLE.

Upon reset, the demo will print a welcoming message to the terminal, indicating the name of the demo and displaying “Advertising.” The terminal will also periodically display the QEI data, including the position/pulse counter and velocity, every second. In accordance with the QEI specification, the velocity register (VELxCNT) is read, and consequently reset, every 1ms in the TC0 callback, however the pulse counter register (POSxCNT) is read every 1s and the information printed.

When a device connects, the terminal will show “Connected.” If the device disconnects, a “Disconnected” message will appear, and the PIC32WM-BZ6204UE will resume advertising, prompting another “Advertising” message.

These messages can be viewed using a terminal emulator like TeraTerm with the following settings:
  • Speed: 115200
  • Data: 8-bit
  • Parity: none
  • Stop bits: 1 bit
  • Flow control: none
The PIC32WM-BZ6204UE will send the QEI data to the connected smartphone, and the MBD app will display the QEI data as shown on the terminal.

Testing

This section assumes that user has programmed the Application Example on the PIC32-BZ6 Curiosity Board.
Figure 5-260. Hardware Setup
Table 5-70. Pin Table
Pin LocationPin on PIC32-BZ6Motor Pin
GPIO HeaderPB10Encoder B Vout (white wire)
GPIO HeaderPB5Encoder A Vout (yellow wire)
Mikrobus 2+5VEncoder Vcc (blue wire)
GPIO HeaderGroundEncoder Ground (green wire)
AC/DC AdapterAC/DC Adapter (-)Motor (-) (black wire)
AC/DC AdapterAC/DC Adapter (+)Motor (+) (red wire)

  • Configure the hardware as shown in the Hardware Setup image above following the pin table. Reset the PIC32-BZ6 Curiosity Board, open a terminal emulator like Tera Term, and select the right COM port@ (Speed: 115200, Data: 8-bit, Parity: none, stop bits: 1 bit, Flow control: none).
  • Upon reset, the following is displayed. The motor information is continuously printed every one second on TeraTerm:
    Note: Pulse counter may be 0, 1, or -1 upon reset.
  • Open MBD on your smartphone. Navigate to BLE UART then PIC32CXBZ and search for “pic32cx-bz6.” Connect to the device and select the transparent option. From here you can enable the “Display Data” checkbox to begin viewing the QEI data.

Note: Some iOS users may not find the device “pic32cx-bz6” in the “PIC32CXBZ” page in MBD. In this case, users can select “BM70” on MBD and follow the same instructions.
  • Supply power to the motor by plugging in the AC/DC adapter
    • When the Motor (-) is connected to AC/DC Adapter (-) and Motor (+) is connected to AC/DC Adapter (+), the motor will counter-clockwise, the pulse count will decrease, and the velocity will be negative.
    • The QEI provides a Velocity Counter (VELxCNT) register that increments or decrements based on the signal from the encoder. This register is reset any time it is read, and we read it every 1ms or at a rate of 1 kHz. The pulse count is read and printed every one second.

      The velocity counter specifies the distance traveled between the time interval of each sample. The velocity at time t can be calculated by subtracting the pulse count at time t by the pulse count at time t-1.

      For example, -10402 – (-5755) = -4647, and -15058 – (-10402) = -4656, and so on.

    • The QEI provides an interface for capturing information about the motor direction, speed, and position. The encoder sends signals which are captured and analyzed by the QEI. The two signals look like this on an oscilloscope:
    • If the QEA signal leads the QEB signal, the motor is deemed positive or forward. If QEB leads QEA, the motor is deemed negative or reverse. The yellow signal in the image is QEA and the green signal is QEB, therefore the motor is in reverse.
    • The quadrature decoder increments a counter (POSxCNT) when QEA leads QEB and decrements the counter when QEB leads QEA, therefore the Pulse Counter is decreasing.
    • Additionally, for increased resolution, the QEI provides a x4 mode which multiplies the input signals by a factor of four. This mode is evident in the Pulse Counter in the TeraTerm output.
  • Unplug the AC/DC adapter. Swap the Motor (-) and Motor (+) pins such that the AC/DC Adapter (-) is connected to Motor (+) and AC/DC Adapter (+) is connected to Motor (-).
  • Supply power to the motor by plugging in the AC/DC adapter:
    • Since the Motor (+) and (-) pins were swapped, the motor will now rotate clockwise, the pulse count will increase, and the velocity will be positive. Notice that the pulse count will resume counting from where it left off, the count will not be reset unless the board is reset.
    • Now the QEA signal (blue) is leading the QEB signal (yellow), so the motor is deemed positive or forward:
  • When the motor is spinning and the power is removed, the velocity will go to 0 and the counter will stop incrementing or decrementing and remain the same.

Important Note About Unexpected QEI Position Counter

Some combinations of duty cycle and phase shift for the QEA and QEB signals may induce an unexpected position counter in the overall result. For example, a 60/40 duty cycle with 90deg phase shift will increment and decrement the position counter within the same cycle. See the below waveform:

This combination of duty cycle and phase shift causes the position counter to oscillate while the motor is spinning, which is an unexpected result.

By definition of the QEI module, if QEA leads QEB then the direction is deemed positive and if QEB leads QEA then the direction is deemed negative. From the waveform image we can see that the QEI is operating as expected by definition, but it is the combination of duty cycle and phase shift that induced this unexpected position counter, not the QEI module itself.

Be aware that other combinations of duty cycle and phase shift may also produce similar unexpected overall results of the position counter.

Developing the Application from Scratch using the MPLAB Code Configurator

Follow the steps below to build the application manually:
Note: It is recommended for the new users of the MPLAB Code Configurator to refer MPLAB® Code Configurator (MCC) User’s Guide in Reference Documentation from Related Links.
  1. Create a new harmony project. For more details, see Creating a New MCC Harmony Project from Related Links.
  2. Import component configuration --This step helps users setup the basic components and configuration required to develop this application. The imported file is of format .mc3 and is located in the path “<Harmony Content Path>\wireless_apps_pic32_bz6\apps\ble\advanced_applications\qei_peripheral_trp_uart\firmware\qei_peripheral_trp_uart.X”.
  3. Accept dependencies or satisfiers when prompted.
  4. Verify if the Project Graph window has all the expected configuration
Note: Make sure that the macro “configUSE_TICKLESS_IDLE” is set to 0. The macro is available in FreeRTOSConfig.h file.
#define configUSE_TICKLESS_IDLE 0

Verifying Advertisement, Connection and Transparent UART Profile Configuration

  1. Select BLE_Stack component in Project Graph.
  2. Select Transparent Profile component in Project Graph.

Verifying QEI Configuration

  1. Select QEI component in the Project Graph.

Verifying Timer Configuration

  1. Select TC0 component in the Project Graph.

Verifying SERCOM Configuration

  1. Select SERCOM0 component in the Project Graph.

Verifying the Pin Configuration

  1. Select Pin Configuration under Plugins in the Project Graph:
  2. Verify the Pin Settings:
    1. These pin configurations designate the GPIO pins RB5 and RB10 for QEI input signals, allowing them to receive the QEA and QEB output signals from the motor.

Files and Routines Automatically generated by the MCC

After generating the program source from MCC interface by clicking Generate Code, the BLE configuration can be found in the following project directories:

Initialization routines for OSAL, RF System, and BLE System are auto-generated by the MCC. See OSAL Libraries Help in Reference Documentation from Related Links. Initialization routine executed during program initialization can be found in the project file.C.

The BLE stack initialization routine executed during Application Initialization can be found in project files. This initialization routine is automatically generated by the MCC. This call initializes and configures the GAP, GATT, SMP, L2CAP and BLE middleware layers.
Autogenerated, Advertisement Data Format
Figure 5-261. AD Structures and Types
Table 5-71. Source File
Source FilesUsage
app.cApplication State machine, includes calls for Initialization of all BLE stack (GAP,GATT, SMP, L2CAP) related component configurations
app_ble\app_ble.cSource Code for the BLE stack related component configurations, code related to function calls from app.c
app_ble\app_ble_handler.cGAP, GATT, SMP and L2CAP event handlers
app_ble\app_trsps_handler.cAll transparent UART server related event handlers
ble_trsps.cAll transparent server functions for user application
Note: app.c is autogenerated and has a state machine based Application code sample, users can use this template to develop their application.

Header Files

  • ble_gap.h: This header file contains BLE GAP functions and is automatically included in the app.c file
  • ble_trsps.h: This header file associated with API’s and structures related to BLE Transparent Client functions for Application User.

Function Calls

MCC generates and adds the code to initialize the BLE Stack GAP, GATT, L2CAP and SMP in APP_BleStackInit() function

  • APP_BleStackInit() is the API that will be called inside the Applications Initial State -- APP_STATE_INIT in app.c

User Application Development

Include
  • ble_trsps/ble_trsps.h in app.c, BLE Transparent UART Server related API's are available here
  • stdio.h in app.c
  • peripheral/sercom/usart/plib_sercom0_usart.h in app_ble_handler.c
  • Include the user action. For more information, refer to User Action from Related Links.
  • definitions.h must be included in all the files, where UART will be used to print debug information.
    Note: definitions.h is not specific to UART but instead must be included in all the application source files where any peripheral functionality will be exercised.

Starting QEI, TC0, and Advertisement

  • QEI_Start();
  • TC0_TimerCallbackRegister(TC0_Callback_InterruptHandler, (uintptr_t)NULL);
  • TC0_TimerStart();
  • BLE_GAP_SetAdvEnable(0x01, 0);

Connected and Disconnected Events

  • In app_ble_handler.c "BLE_GAP_EVT_CONNECTED" event will be generated when a BLE connection is completed

Connection Handler

  • Connection handle associated with the peer peripheral device needs to be saved for data exchange after a BLE connection

  • p_event->eventField.evtConnect.connHandle has this information

  • Start advertising upon disconnection

Transmit CAN/CAN-FD Message to CAN Bus Analyzer FD Tool

  • Add “APP_MSG_QEI_EVT” to the generated APP_MsgId_T.
  • BLE_TRSPS_SendData(); is the API to be used for sending data towards the central device.
Note: The precompiled application example uses a TC0 callback to initiate the data transmission upon receiving a TC0 interrupt every 1 ms.

Example Implementation for Transmitting the QEI data using the BLE_TRSPS_SendData() API

#define VELCOITY_FREQ                       1000
#define SERCOM_TX_BUFFER_SIZE               100

uint16_t conn_hdl;// connection handle info captured @BLE_GAP_EVT_CONNECTED event
uint8_t txBuffer[SERCOM_TX_BUFFER_SIZE];
uint32_t frequency;
/* This function is called after period expires */
void TC0_Callback_InterruptHandler(TC_TIMER_STATUS status, uintptr_t context)
{
    APP_Msg_T   appMsg;
    
    if(++frequency == VELCOITY_FREQ)
    {
        frequency = 0 ;
        uint32_t nBytes=0;
        int32_t position = QEI_PositionGet();
        int32_t velocity = QEI_VelocityGet(); 
        appMsg.msgId = APP_MSG_QEI_EVT;
        
        nBytes = sprintf((char*)txBuffer, "Pulse Counter=%li, Velocity at %iHz=%li \r\n", position, VELCOITY_FREQ, velocity);
        SERCOM0_USART_Write((uint8_t*)txBuffer, nBytes); 
        
        appMsg.msgData[0] = nBytes;
        memcpy(appMsg.msgData+1, txBuffer, nBytes);
        OSAL_QUEUE_Send(&appData.appQueue, &appMsg, 0);     
    }
}

else if(p_appMsg->msgId==APP_MSG_QEI_CB)
{
BLE_TRSPS_SendData(conn_hdl, p_appMsg->msgData[0], &p_appMsg->msgData[1]);
}
Note: Users can explore more BLE Advertisement functionalities using the BLE Stack APIs. For more information, refer to BLE Stack in Reference Documentation from Related Links.

Where to go from here

  • BLE Sensor App utilizes the Transparent UART building block, see BLE Sensor from Related Links.