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.
Recommended Reading
-
Getting Started with Application Building Blocks – See Building Block Examples from Related Links.
-
Getting Started with Peripheral Building Blocks – See Peripheral Devices from Related Links.
- See BLE Connection from Related Links.
- See BLE Transparent UART from Related Links.
- BLE Software Specification – See MPLAB® Harmony Wireless BLE in Reference Documentation from Related Links.
Hardware Requirement
S. No. | Tool | Qty |
---|---|---|
1 | PIC32-BZ6 Curiosity Board | 1 |
2 | Micro USB cable | 1 |
3 | Hall Encoder DC Motor | 1 |
4 | AC/DC Adapter | 1 |
SDK Setup
Refer to Getting Started with Software Development from Related Links.
Software Requirement
-
To install Tera Term tool, refer to the Tera Term web page in Reference Documentation from Related Links.
Smart phone App
- Microchip Bluetooth® Data (MBD)
Programming the Precompiled Hex File or Application Example
Using MPLAB® X IPE:
- Import and program the precompiled hex
file:
<Harmony Content Path>\wireless_apps_pic32_bz6\apps\ble\peripheral_applications\qei_peripheral_trp_uart\precompiled_hex
. - 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:
- Perform the following the steps mentioned in Running a Precompiled Example. For more information, refer to Running a Precompiled Application Example from Related Links.
- Open and program the application
“
qei_peripheral_trp_uart.X
” located in “<Harmony Content Path>\wireless_apps_pic32_bz6
” using MPLAB X IDE.\apps\ble\ peripheral _applications\qei_peripheral_trp_uart\firmware
- 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.
- Speed: 115200
- Data: 8-bit
- Parity: none
- Stop bits: 1 bit
- Flow control: none
Testing
Pin Location | Pin on PIC32-BZ6 | Motor Pin |
---|---|---|
GPIO Header | PB10 | Encoder B Vout (white wire) |
GPIO Header | PB5 | Encoder A Vout (yellow wire) |
Mikrobus 2 | +5V | Encoder Vcc (blue wire) |
GPIO Header | Ground | Encoder Ground (green wire) |
AC/DC Adapter | AC/DC Adapter (-) | Motor (-) (black wire) |
AC/DC Adapter | AC/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.
- 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.
- 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.
- 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:
- 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.
- 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
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
- Create a new harmony project. For more details, see Creating a New MCC Harmony Project from Related Links.
- 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
”. - Accept dependencies or satisfiers when prompted.
- Verify if the Project Graph window has
all the expected configuration
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
-
Select BLE_Stack component in Project Graph.
- Select Transparent Profile
component in Project Graph.
Verifying QEI Configuration
-
Select QEI component in the Project Graph.
Verifying Timer Configuration
-
Select TC0 component in the Project Graph.
Verifying SERCOM Configuration
-
Select SERCOM0 component in the Project Graph.
Verifying the Pin Configuration
-
Select Pin Configuration under Plugins in the Project Graph:
- Verify the Pin Settings:
- 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.
Generating Code
For more details on code generation, refer to MPLAB Code Configurator (MCC) Code Generation from Related Links.
Files and Routines Automatically generated by the MCC
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
.
Source Files | Usage |
---|---|
app.c | Application State machine, includes calls for Initialization of all BLE stack (GAP,GATT, SMP, L2CAP) related component configurations |
app_ble\app_ble.c | Source Code for the BLE stack related component configurations, code related to
function calls from app.c |
app_ble\app_ble_handler.c | GAP, GATT, SMP and L2CAP event handlers |
app_ble\app_trsps_handler.c | All transparent UART server related event handlers |
ble_trsps.c | All transparent server functions for user application |
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 fileble_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
inapp.c
User Application Development
ble_trsps/ble_trsps.h
inapp.c
, BLE Transparent UART Server related API's are available herestdio.h
inapp.c
peripheral/sercom/usart/plib_sercom0_usart.h
inapp_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 generatedAPP_MsgId_T
.
BLE_TRSPS_SendData()
; is the API to be used for sending data towards the central device.
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]);
}
Where to go from here
- BLE Sensor App utilizes the Transparent UART building block, see BLE Sensor from Related Links.