Skip to main content
Senior III
June 23, 2025
Question

Sending sensor data via BLE

  • June 23, 2025
  • 10 replies
  • 1525 views

P-Nucleo STM32WB55

I have two 3-axis accelerometers & toe temperature sensors on an I2C bus. I taking measurements at 1 Hz.

I would like to send this data over BLE. Every tutorial so far seems to skip how to read the data into a characteristic & then send it. At this point I am only interested in broadcasting.

I've managed to set up an attribute for reading, given the service its names. I can see the device & the service advertised on my phone via ST's BLE app. So how do I get the data into the service?

I'm going around in circles here!!

Please no "have you looked at the examples", yes I have they aren't making any sense to me, I need to talk to a human about this.

10 replies

FilipKremen
ST Employee
June 24, 2025

Hello,

for your use case, I think BLE_HeartRate example would be a good reference project.

In this example there is a sensor measurement simulation. If you open hrs_app.c file, you can see there HRSAPP_Init() function. The first function registers the measurement task in the sequencer.

(You can find more information about sequencer here Utility:Sequencer - stm32mcu) It's a basically scheduler for tasks. Once the task is registered in the sequencer, it can be run from sequencer. The function HRSAPP_Measurement() is getting value from sensor (in this case reading from RTC) and then it

 UTIL_SEQ_RegTask( 1<< CFG_TASK_MEAS_REQ_ID, UTIL_SEQ_RFU, HRSAPP_Measurement );

 updates the characteristic value with this function below.

HRS_UpdateChar(HEART_RATE_MEASURMENT_UUID, (uint8_t *)&HRSAPP_Context.MeasurementvalueChar);

Now when you have the function for measuring the values and writing into the characteristic, it can be called periodically with timerservers. The code below creates a timer which is triggered periodically, and it runs the measurement.

HW_TS_Create(CFG_TIM_PROC_ID_ISR, &(HRSAPP_Context.TimerMeasurement_Id), hw_ts_Repeated, HrMeas);

You can start the timer to run periodically with HRSAPP_MEASUREMENT_INTERVAL with this function below.

HW_TS_Start(HRSAPP_Context.TimerMeasureHRSAPP_MEASUREMENT_INTERVALment_Id, HRSAPP_MEASUREMENT_INTERVAL);

 I strongly recommend having a look at the links below to better understand.

How to build wireless applications with STM32WB MCUs - Application note

STM32WB Getting Started Series - YouTube

If you need to explain any step, please don't hesitate to ask.

Best regards,

Filip Kremen

Senior III
June 25, 2025

Well I would look at the example but the "Example Selector" just keeps crashing CubeIDE

FilipKremen
ST Employee
June 25, 2025

Hello,

please try to open the example directly from Windows explorer.

Best regards,

Filip Kremen

Senior III
June 25, 2025

Hmmm now the board doesn't show when using either ST BLE Toolbox or ST BLE Sensor.

Previously the board would show up but now I've flashed with the HRS example its not showing.

FilipKremen
ST Employee
June 25, 2025

Do you see any BLE traces when you open terminal?

Probably FUS is running there instead of wireless FW. Please open STM32CubeProgrammer and press the "Start Wireless Stack" button and then upload the example again.

STM32WB Firmware Upgrade Service - stm32mcu

Best regards,

Filip Kremen

Senior III
June 25, 2025

No BLE traces.

Opened STM32CubeProgrammer and pressed "Start Wireless Stack" button and then uploaded the example again, still not showing.

When I upload my own code I can see the device (although confusingly not when I enable the ST device filters?!?!).

Honestly I just want to be able to broadcast the data. The heart rate monitor code (even if it worked) seems overly complex & nested/cryptic. Surely there's an easier way than all that abstraction?

FilipKremen
ST Employee
June 25, 2025

You can enable the debug traces as mentioned here. (4.6)

STM32WB Bluetooth® LE – Heart Rate Sensor Project - stm32mcu

Also, please try to debug the project if it is stuck somewhere.

If you want to broadcast only, possibly BLE_Beacon example could be a better choice.

STM32WBA Bluetooth® Low Energy – Beacon - stm32mcu

Best regards,

Filip Kremen

Senior III
June 25, 2025

Sorry but this is still really opaque. As I've tried to explain since the OP, there is so much redirection & abstraction going on with the examples I just cant find an answer to my question in them. Even the way the projects are structured is unintuitive (e.g the includes hidden away in the binaries folder? who does that?)

I am happy to generate my own scheduling, I just need to know how to load the BLE package with data & transmit it! This is completely opaque in the examples (which dont work & for which the YouTube videos are years out of date).

 

FilipKremen
ST Employee
June 25, 2025

I agree that it might look complicated at first time.

Have you watched the STM32WB getting started series on YT that I sent you?

It's useful to watch it for better overview and there is also a video regarding sending the data.

Also, if you could share your project, I could help you further with your application.

Best regards,

Filip Kremen

 

Senior III
June 25, 2025

Thankyou, yes, I watched the series prior to posting & have watched it since. It just doesn't go into the detail needed & skips bits of information on how to just do basic operations with BLE at a code level. Also its at least 4 years out of date with the current examples.

I've even did an online course that says it was specifically for the STM32WB55 which also fails to just go into the basic API calls to use BLE but spent a lot of time explaining what BLE was. So I get the whole layer thing, the services, attributes, characteristics, how to flash the firmware onto the M0, how to set up in CubeIDE, etc. Just not how to populate said characteristics with data.

Find attached my project, I'm reading data from 2 x ADT7410 temperature sensors & 2x ADXL345 3-axis accelerometers over an I2C bus. Currently I'm sending this over UART via the ST-Link to a terminal on my laptop.
I would like to also broadcast the same data via BLE. As it stands I can see the board when I open up ST BLE Toolbox, so I know its advertising OK.

 

 

FilipKremen
ST Employee
June 26, 2025

Hello,

I have modified your project and moved your code to custom_app.c file.

In the while loop there should be only MX_APPE_Process() function for running the sequencer.

If you have a look at Custom_APP_Init() function, you will see there a task for reading data from sensors and updating the characteristic value. This task is set to run periodically each second.

You can update the characteristic value with Custom_STM_App_Update_Char() function as it is done in sensor_update() function. I have increased the length of the characteristic just for demonstration, you can change the length in STM32CubeMX configuration. Variable "data" is used for sending the values, you can add there your own real values from the sensors. If you open ST BLE Toolbox and enable notification in Sensors service, you can see how the value is changing each second. I'm attaching the project also with git, so you can see the changes in any git client.

Please let me know if you need any further explanation.

Best regards,

Filip Kremen

 

Senior III
June 30, 2025

Hi thankyou Filip, this is making much more sense now.

As far as the "data" variable goes, I'm assuming that this has to be uint8_t for transmission. In which case will I have to parse my floats to 4 x uint8_t prior to transmission?  

FilipKremen
ST Employee
June 30, 2025

Hello,

yes, that's correct. The input parameter for function Custom_STM_App_Update_Char() is an array of uint8_t.

You can work with bytes on the MCU and then convert it to floats in your mobile app, however you have to implement it in your own mobile app.

Best regards,

Filip Kremen

Senior III
June 30, 2025

I've added my sensors following the config you provided each with its own service & characteristic, see below

When I check using LightBlue I can see the device, link to it & read the characteristics of each service. The only problem now is that the values read are all the same 0x0000C341?

The values coming through the UART are as expected. Any idea what I'm not getting here?

union sensor_val
{
	float sensor_float;
	uint8_t sensor_bytes[4];
};

void sensor_update(void)
{
	 /* Temperature sensors */
	union sensor_val temp_val_0;
	union sensor_val temp_val_1;

	ADT7410_ReadTemp(&temp_0);
	temp_val_0.sensor_float = temp_0.deg_data;

	ADT7410_ReadTemp(&temp_1);
	temp_val_1.sensor_float = temp_1.deg_data;

	printf("Temperature sensor 0 : %f\r\n", temp_0.deg_data);
	printf("Temperature sensor 1 : %f\r\n", temp_1.deg_data);

	/* Accelerometers */
	acceleration_t ADXL345_data_0;
	union sensor_val accel_x_0;
	union sensor_val accel_y_0;
	union sensor_val accel_z_0;

	acceleration_t ADXL345_data_1;
	union sensor_val accel_x_1;
	union sensor_val accel_y_1;
	union sensor_val accel_z_1;

	ADXL345_ReadAcc(&acc_0, &ADXL345_data_0);
	accel_x_0.sensor_float = ADXL345_data_0.ax;
	accel_y_0.sensor_float = ADXL345_data_0.ay;
	accel_z_0.sensor_float = ADXL345_data_0.az;

	ADXL345_ReadAcc(&acc_1, &ADXL345_data_1);
	accel_x_1.sensor_float = ADXL345_data_1.ax;
	accel_y_1.sensor_float = ADXL345_data_1.ay;
	accel_z_1.sensor_float = ADXL345_data_1.az;

	Custom_STM_App_Update_Char(CUSTOM_STM_T_0, (uint8_t *)&temp_val_0.sensor_bytes);
	Custom_STM_App_Update_Char(CUSTOM_STM_T_1, (uint8_t *)&temp_val_1.sensor_bytes);

	Custom_STM_App_Update_Char(CUSTOM_STM_X_0, (uint8_t *)&accel_x_0.sensor_bytes);
	Custom_STM_App_Update_Char(CUSTOM_STM_Y_0, (uint8_t *)&accel_y_0.sensor_bytes);
	Custom_STM_App_Update_Char(CUSTOM_STM_Z_0, (uint8_t *)&accel_z_0.sensor_bytes);

	Custom_STM_App_Update_Char(CUSTOM_STM_X_1, (uint8_t *)&accel_x_1.sensor_bytes);
	Custom_STM_App_Update_Char(CUSTOM_STM_Y_1, (uint8_t *)&accel_y_1.sensor_bytes);
	Custom_STM_App_Update_Char(CUSTOM_STM_Z_1, (uint8_t *)&accel_z_1.sensor_bytes);
}

 

 

FilipKremen
ST Employee
July 1, 2025

Hello,

could you please send me the project again?

Thank you.

 

Best regards,

Filip Kremen

Senior III
July 1, 2025

Thanks, find attached.

I routed some debugger messages to the UART from the Custom_STM_App_Update_Char() function which which report that the aci_gatt_update_char_value() returns BLE_STATUS_SUCCESS for every characteristic.

I further noticed that the value is different today, it alternates between 0x0000B041 and 0x0080B041 for all characteristics.

 

 

FilipKremen
ST Employee
July 2, 2025

Hello,

I have checked your project, and I think that you haven't assigned unique UUID for each service and characteristic. (all are 00 00)

I couldn't see all the services and I also couldn't read properly the characteristics. Please change the UUID for each service and characteristic and let me know if you can continue with your project.

Thank you.

 

Best regards,

Filip Kremen

Senior III
July 3, 2025

Ahhh yes thankyou that appears to be it!
I naively assumed that MX would autogenerate the UUID for each characteristic.

Thanks again for walking me through this. Its all making so much more sense now.

Senior III
July 3, 2025

Just a note, ST BLE Toolbox crashes when I connect the device yet LightBlue has no problems.

FilipKremen
ST Employee
July 16, 2025

Hello,

I'm glad it's working for you. 

Does the app crash always on your side?

I also noticed it crashes sometimes.

Best regards,

Filip Kremen

 

 

Senior III
July 29, 2025

Sorry for the late reply, been on annual leave.

So far it hasn't crashed. I'll leave it on for a few day & see what happens.