IOT

How to Create BLE Project using STM32 Microcontroller & BlueIO

We’ll learn how to make a BLE project with an STM32 microcontroller and BlueIO in this tutorial. The project is a simple demonstration of how to set up a STM32Cube project as a USB CDC Host capable of talking with the BleuIO Dongle. in a short amount of time.

The STM32 will identify a BleuIO Dongle when it is connected to the Nucleo board’s USB connection. The BleuIO Dongle will then accept one of three UART inputs and transmit one of three preprogrammed commands according to the input. The following commands are used in this example:

  • ATI(Dongle Information)
  • AT+ADVSTART(Starts Advertising)
  • AT+ADVSTOP(Stops Advertising)

We used a micro mbed-Enabled Development Nucleo-144 series ARM® Cortex®-M7 MCU 32-Bit Embedded Evaluation Board with an STM32H743ZI microcontroller. We’ll develop a demo BLE project using the same STM32 Microcontroller and BlueIO as in the previous example.

If you want to use a different setup, make sure it supports a USB Host, and keep in mind that the GPIO setup may be different and that the.ioc file may need to be modified.

About the Code,

You can get the project here: https://github.com/smart-sensor-devices-ab/stm32_bleuio_example

This project-based on a new STM32 project with these changes in the .ioc file. Under ‘Connectivity’ the ‘USB_OTG_FS’-mode is changed to Host_Only and in the NVIC Settings all global interrupts are enabled.

And under ‘Middleware’ the ‘USB_HOST’- ‘Class for FS IP’ is set to ‘Communication Host Class (Virtual Port Com)’.

To make sure the host would recognize when the bootloader is done and the BleuIO firmware is running this was added in the USBH_UserProcess function in ‘usb_host.c’ (found under ‘USB_HOST’ -> ‘App’ folder).

static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id)
{
/* USER CODE BEGIN CALL_BACK_1 */
switch(id)
{
case HOST_USER_SELECT_CONFIGURATION:
break;

case HOST_USER_DISCONNECTION:
Appli_state = APPLICATION_DISCONNECT;
isBleuIOReady = false;

// Turn on Red LED, turn off Green and Yellow LED
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
break;

case HOST_USER_CLASS_ACTIVE:
Appli_state = APPLICATION_READY;
// Check if BleuIO firmware is running
// (idProduct:0x6001 = bootloader, idProduct:0x6002 = bleuio fw)
if(phost->device.DevDesc.idProduct == 0x6002)
{
isBleuIOReady = true;
// Sends message to uart that BleuIO is connected and ready
HAL_UART_Transmit(&huart3, (uint8_t*)BLEUIO_READY, strlen(BLEUIO_READY), HAL_MAX_DELAY);

// Turn on Green LED, turn off Yellow and Red LED
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);

// Start receiving from usb
USBH_CDC_Receive(&hUsbHostFS, CDC_RX_Buffer, RX_BUFF_SIZE);
}
break;

case HOST_USER_CONNECTION:
Appli_state = APPLICATION_START;
isBleuIOReady = false;
// Turn on Yellow LED, turn off Green and Red LED
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);
break;

default:
break;
}
/* USER CODE END CALL_BACK_1 */
}

About the Code

The Nucleo board’s Green, Red, and Yellow LEDs are also programmed to change colour according on the connection state.

Red = Disconnnected

Yellow = Connecting

Green = Connected

  • The status of the dongle is also accessible from the main.c section thanks to an external variable bool BleuIOReady.
  • Once the BleuIO dongle is confirmed to be connected the USBH_CDC_Receive function is run to start receiving data from the USB CDC. The USBH_CDC_ReceiveCallback also needs to be implemented.
void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)
{
if(phost == &hUsbHostFS)
{
// Handles the data recived from the USB CDC host, here just printing it out to UART
rx_size = USBH_CDC_GetLastReceivedDataSize(phost);
HAL_UART_Transmit(&huart3, CDC_RX_Buffer, rx_size, HAL_MAX_DELAY);

// Reset buffer and restart the callback function to receive more data
memset(CDC_RX_Buffer,0,RX_BUFF_SIZE);
USBH_CDC_Receive(phost, CDC_RX_Buffer, RX_BUFF_SIZE);
}

return;
}
  • The received data is just echoed to the UART in this case.
  • The USBH CDC Transmit function is used to send data to the Dongle. UART input is utilized to deliver various commands in this example. A wrapper function that may be accessed from the main has been constructed for this purpose. c.
/**
* @brief Simple function that takes a string and transmits it to the dongle
* @retval None
*/
void writeToDongle(uint8_t * cmd)
{
USBH_CDC_Transmit(&hUsbHostFS, cmd, strlen((char *)cmd));
}

In main.c HAL_UART_RxCpltCallback is implemented to receive input from Uart and a simple UART input handler.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if(UartHandle == &huart3)
{
RX_value = (int)aRxBuffer[0];
uartStatus = UART_RX_NONE;

switch(RX_value)
{
case UART_RX_0:
{
uartStatus = UART_RX_0;
break;
}
case UART_RX_1:
{
uartStatus = UART_RX_1;
break;
}
case UART_RX_2:
{
uartStatus = UART_RX_2;
break;
}
default:
{
uartStatus = UART_RX_NONE;
break;
}
}
// Resets uart recieve interrupt mode
HAL_UART_Receive_IT(&huart3, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
}
}


/**
* @brief Simple uart input handler
* @retval None
*/
void handleUartInput(UARTCommandTypeDef cmd)
{
switch(cmd)
{
case UART_RX_0:
{
// 0
uart_buf_len = sprintf(uart_tx_buf, “\r\n(0 pressed)\r\n”);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
if(isBleuIOReady)
{
writeToDongle((uint8_t*)DONGLE_CMD_ATI);
} else
{
uart_buf_len = sprintf(uart_tx_buf, BLEUIO_NOT_READY_MSG);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_1:
{
// 1
uart_buf_len = sprintf(uart_tx_buf, “\r\n(1 pressed)\r\n”);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
if(isBleuIOReady)
{
writeToDongle((uint8_t*)DONGLE_CMD_AT_ADVSTART);
} else
{
uart_buf_len = sprintf(uart_tx_buf, BLEUIO_NOT_READY_MSG);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_2:
{
// 2
uart_buf_len = sprintf(uart_tx_buf, “\r\n(2 pressed)\r\n”);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
if(isBleuIOReady)
{
writeToDongle((uint8_t*)DONGLE_CMD_AT_ADVSTOP);
} else
{
uart_buf_len = sprintf(uart_tx_buf, BLEUIO_NOT_READY_MSG);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_NONE:
{
break;
}
default:
{
uartStatus = UART_RX_NONE;
break;
}
}
}

The handleUartInput() handles the inputs 0, 1, and 2 and maps each to certain Dongle commands. The handler is then put inside the main loop.

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_USB_HOST_Process();
/* USER CODE BEGIN 3 */
// Simple handler for uart input
handleUartInput(uartStatus);
}
/* USER CODE END 3 */

Using the example project

We’ll need the following hardware and software to make a BLE project with an STM32 microcontroller and BlueIO.

STM32 BLE

How to Setup the Project

Downloading the project from GitHub

Get the project from here: https://github.com/smart-sensor-devices-ab/stm32_bleuio_example

Either clone the project or download it as a zip file and unzip it, into your STM32CubeIDE workspace.

Importing as an Existing Project

From STM32CubeIDE choose File>Import…

Then select General>Integrate Existing Projects into Workspace and then ‘Next >’.

  • Make sure you’ve selected your workspace from the ‘Select root directory:’ drop-down menu.
  • You should see the “stm32 bleuio example” project, double-check it, and then click “Finish.”/p>
STM32 BlueIO BLE

Running the example

  • To build the project in STMCubeIDE, click the hammer symbol.
  • Use a serial terminal emulator program like TeraTerm, Putty, or CoolTerm to access the ‘STMicroelectronics STLink Virtual COM Port.’Serial port Setup:
  • Baudrate: 115200
  • Data Bits: 8
  • Parity: None
  • Stop Bits: 1
  • Flow Control: None
  • To flash and run it on your board, press the green play button in STMCubeIDE. The ‘Run Configuration’ window will appear the first time you click it. You can simply click run and leave it as is.
  • Connect the BleuIO Dongle to your computer.
  • Wait until you see the message “[BleuIO Dongle Ready].”

– Press 0 to get device information:

1 to start advertising:

2 to stop advertising:

The response from the Dongle will be printed to UART.

This is how you can create BLE Project using STM32 Microcontroller & BlueIO. 

Leave a Reply

Your email address will not be published.