cancel
Showing results for 
Search instead for 
Did you mean: 

Integrate BNO055 sensor code to Touchgfx compass UI

Prajyot1
Associate III

Prajyot1_0-1742555144172.png

Hello , 
i am using STM32h750B-dk . i took compass image (PNG file) as texture mapper and i want to rotate the compass image according to BNO055 sensor which is magnetometer. this is connected through I2C4 (for I2C4 , STmod+ is used). i have share the codes. Thank you!
#Model.cpp:

#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>
#include <cstdint>
#include "stm32h7xx_hal.h"
#include <math.h>


#define BNO055_I2C_ADDR (0x28 << 1)  // Shifted for STM32 HAL
#define BNO055_MAG_DATA_X_LSB_ADDR  0x0E


extern I2C_HandleTypeDef hi2c4;

Model::Model() : modelListener(0)
{

}

void Model::tick()
{
	static uint32_t lastUpdateTime = 0;
	uint32_t currentTime = HAL_GetTick();
	if ((currentTime - lastUpdateTime) >= 1000)  // Check if 1 second has passed
	    {
	        lastUpdateTime = currentTime;

	 if (modelListener)
	    {
	        int heading = getHeading();
	        modelListener->updateHeading(heading);
	    }
	   }
}
int Model::getHeading()
{
    uint8_t buffer[6];
    int16_t mag_data[3];

    // Read magnetometer data
    HAL_I2C_Mem_Read(&hi2c4, BNO055_I2C_ADDR, BNO055_MAG_DATA_X_LSB_ADDR, I2C_MEMADD_SIZE_8BIT, buffer, 6, HAL_MAX_DELAY);

    // Convert to signed 16-bit values
    mag_data[0] = (int16_t)((buffer[1] << 8) | buffer[0]);  // X-axis
    mag_data[1] = (int16_t)((buffer[3] << 8) | buffer[2]);  // Y-axis
    mag_data[2] = (int16_t)((buffer[5] << 8) | buffer[4]);  // Z-axis

    // Calculate heading angle (in degrees)
    float heading = atan2((float)mag_data[1], (float)mag_data[0]) * (180.0f / 3.14159265359f);

    if (heading < 0)
        heading += 360;  // Normalize to 0-360°

    return (int)heading;
}

#Screen1Presenter.cpp:

#include <gui/screen1_screen/Screen1View.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>

Screen1Presenter::Screen1Presenter(Screen1View& v)
    : view(v)
{

}

void Screen1Presenter::activate()
{

}

void Screen1Presenter::deactivate()
{

}
void Screen1Presenter::updateHeading(int heading)
{
    view.updateCompass(heading); // Send heading to the UI for display

}

#Screen1View.cpp:

#include <gui/screen1_screen/Screen1View.hpp>

Screen1View::Screen1View()
{

}

void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
}

void Screen1View::tearDownScreen()
{
    Screen1ViewBase::tearDownScreen();
}

void Screen1View::updateCompass(int heading)
{
    float angleRadians = heading * 3.14159265359f / 180.0f;
    textureMapper1.setAngles(0,0,angleRadians);
    textureMapper1.invalidate();
}

 

 

33 REPLIES 33

Please show the actual output you get from your printfs - a screenshot or copy/paste text from your terminal

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

ok.

Prajyot1_0-1742992315152.png

Prajyot1_2-1742992363820.png

Prajyot1_3-1742992391482.png

Prajyot1_1-1742992345642.png

 

That's not the printf output - is it?

I mean the output from these printf statements:

AndrewNeil_0-1742992624101.png

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

Ok, so check the tutorial 3 to see how to manage the model view presenter architecture!

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)

@Andrew Neil the screenshot i have provided i took while debugging. these reading is from model::setHeading() , and in model::tick() , the current Heading gives 0.

ok.. i will check .

But they don't show the output of your printfs - which is what the running code is actually seeing, in real time.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
Kai_Satone
Senior

@Prajyot1 
Try using a Queue to send sensor data from a sensor to Model.cpp and then process it using Model::tick().

Here's what I assume:

  1. You'll have a producer (sensor) that collects data and pushes it to a queue.

  2. The consumer (Model.cpp) will pull data from the queue inside Model::tick().

  3. We’ll use std::queue with a mutex and condition_variable for thread safety.

void Model::tick() {
#ifndef SIMULATOR
    BNO055_Data sensorData;
    // Check for new data without waiting (timeout 0)
    if (osMessageQueueGet(mid_BNO055MsgQueue, &sensorData, nullptr, 0) == osOK) {
        currentHeading = sensorData.heading;
        printf("Model tick: Updated heading from queue: %.2f\n", currentHeading);
    }
#endif

    if (modelListener) {
        printf("Model tick: Sending heading %.2f to presenter\n", currentHeading);
        modelListener->updateHeading(currentHeading);
    }
}

and also there could be some error like Embedded-specific declarations for that you can use 

extern "C" {
}
#endif




i have able to rotate the compass texture mapper. but the wildcard is not updating the value .
here is the video  ->Compass.MOV - Google Drive 

Hello @Prajyot1 ,

 

The wildcard show question marks because you have to add the characters that can be in your wildcard. We do that to ensure that we don't add characters that are not used because they take memory space.

To add characters, go to your typography (the one you use for that textArea) and add characters to the wildcard range (here I put 0-9 to be able to use all the numbers but you can put any char you want). :

GaetanGodart_0-1743163025608.png

 

Regards,

 

Gaetan Godart
Software engineer at ST (TouchGFX)