cancel
Showing results for 
Search instead for 
Did you mean: 

Moving Objects in C++ Application from local to global

NSemrHomeInit
Senior

Hello ST Team,

I am currently working on developing my application in C++ with cubeIde and MX. To achieve this, I have created a C++ file where I have listed all my objects and functions in C++. To incorporate this into my C code, I use the "extern C" mechanism.

My application is centered around the ISM330DLC Accelerometer. I have a question regarding the declaration of global objects. When I attempt to move the objects  AccGyr  and dev_interface outside the myMain loop, treating it as an external objects, I encounter an issue with the TransmiReceive function, which returns Hall_NOK and jump to "Error_Hander".

 

I will be sharing the C++ file shortly. My objective is to relocate the dev_interface and AccGyr inside the myMain() function the code shared.

 

 

 

 

/*
 * mymain.cpp
 *
 *  Created on: 30 nov. 2023
 *      Author: Tarik
 */
#ifdef __cplusplus
extern "C" {
#endif

#include "main.h"
#include "stm32f4xx_hal_gpio.h"

#include "../../BSP/ISM330DLCSensor.h"
#include "../../BSP/SPIClass.h"
#include <cstdio>
#include <cmath>
/************ external objet and external for C++ execution in C*/
extern SPI_HandleTypeDef hspi4;
extern "C" void mymain(void);
extern "C" void AccGyro_call_back_function(void);
/****************************************************************/

#define INTEGRATION  100e-3
#define SENSOR_ODR 104.0f // In Hertz
#define ACC_FS 2 // In g
#define GYR_FS 2000 // In dps
#define MEASUREMENT_TIME_INTERVAL (1000.0f/SENSOR_ODR) // In ms
#define FIFO_SAMPLE_THRESHOLD 199
#define FLASH_BUFF_LEN 8192

/*************** Satic function *********************************/
static void rungeKutta(int32_t *acceleration, float initialVelocity, float timeStep, float *integral);
static void integrate(int32_t *acceleration, float initialVelocity, float timeStep, float *integral);
static void rungeKuttaIntegration(int32_t * tauxRotation, float deltaTime, float * Output);
/****************************************************************/

int32_t accelerometer[3];
int32_t gyroscope[3];
float velocity[3];
float velocity1[3];
float velocity2;
float  angle[3];
float  tauxRotation;
/*****objects ******/

void mymain(void)
{

	HAL_StatusTypeDef STATUS;
	ISM330DLCStatusTypeDef STATUS1;
	SPIClass dev_interface(hspi4);
	ISM330DLCSensor AccGyr(&dev_interface, SPI4_CS_Pin, 1400000);

	uint8_t transerfer = 0xA5;
	uint8_t pRxDATA;
	//hardware test
	for (uint16_t indexer = 0; indexer < 100; indexer++)
	{
		HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_RESET);

		STATUS = HAL_SPI_TransmitReceive(&hspi4, &transerfer, &pRxDATA, 1, 5);

		if (STATUS != HAL_OK)
		{
			Error_Handler();
		}
		HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_SET);
		HAL_Delay(10);
	}

	dev_interface.begin();

	// Initialize IMU.
	STATUS1 = AccGyr.begin();


	if (STATUS1 == ISM330DLC_STATUS_OK) {
		AccGyr.Enable_X();
		AccGyr.Enable_G();
	}

	/* Read the Acc id*/
	uint8_t id;
	float acc_sensitivity= 0.0;
	float gyro_sensitivity= 0.0;

	STATUS1 = AccGyr.ReadID(&id);
	AccGyr.Get_X_Sensitivity(&acc_sensitivity);
	AccGyr.Get_G_Sensitivity(&gyro_sensitivity);

	/* set odr */
	AccGyr.Set_X_ODR(12.0);
	AccGyr.Set_G_ODR(12.0);

	/* read odr */
	float  odr;
    AccGyr.Get_X_ODR(&odr);
    AccGyr.Get_G_ODR(&odr);

    /* set full scale*/
    AccGyr.Set_G_FS(2000.0);
    AccGyr.Set_X_FS(2);

    float fullScale;
    /* get full scale*/
    AccGyr.Get_G_FS(&fullScale);
    AccGyr.Get_X_FS(&fullScale);


	/* Object construction */
	while (1)
	{
		HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
		HAL_Delay(100);

		/*Get accelerometer and gyroscope data in [mg] and [mdps]*/
		AccGyr.Get_X_Axes(accelerometer);
		AccGyr.Get_G_Axes(gyroscope);

		if(accelerometer)
		{
			/* Integration methods */
			rungeKutta(accelerometer, 0, INTEGRATION, velocity);
			integrate(accelerometer, 0, INTEGRATION, velocity1);
		}

		/* Convert m/s to km/h */
		for (uint8_t i = 0; i<3 ; i++)
		{
			velocity[i] = velocity[i];
			velocity1[i] = velocity1[i];
		}

		for(uint8_t i=0; i<3 ; i++)
		{
			//printf(" Runge-Kutta velocity integration: %.3f mm/s, normal integration velocity1: %.3f mm/s for %d \n", velocity[i], velocity1[i], i);
		}


		// Integration de l'angle en utilisant la méthode de Runge-Kutta
		// integrer si la variation est importante
		if (abs(gyroscope[0]) > 1000 && abs(gyroscope[1]) > 1000 && abs(gyroscope[2]) > 1000 )
		{
			rungeKuttaIntegration(gyroscope, INTEGRATION, angle);
		}

		for(uint16_t i=0; i<3 ; i++)
		{
			//printing the angle on the console swv itm data
			printf("L'angle integre avec Runge-Kutta est de : %.3f mdegres indice %d\n",angle[i], i);
		}
	}

}



// Runge-Kutta integration method
static void rungeKutta(int32_t * acceleration, float initialVelocity, float timeStep, float * integral) {

	float k1 = 0.0;
	float k2 = 0.0;
	float k3 = 0.0;
	float k4 = 0.0;
	for (uint8_t i = 0; i<3; i++)
	{
		k1 = acceleration[i];
		k2 = acceleration[i] + 0.5 * k1 * timeStep;
		k3 = acceleration[i] + 0.5 * k2 * timeStep;
		k4 = acceleration[i] + k3 * timeStep;

		integral [i] += initialVelocity + (k1 + 2*k2 + 2*k3 + k4) * (timeStep / 6.0);

	}

}

static void integrate(int32_t* acceleration, float initialVelocity, float timeStep, float * integral) {
    integral[0] = initialVelocity + (acceleration[0] * timeStep);
    integral[1] = initialVelocity + (acceleration[1] * timeStep);
    integral[2] = initialVelocity + (acceleration[2] * timeStep);
}

// Méthode de Runge-Kutta d'ordre 4 pour l'intégration numérique
static void rungeKuttaIntegration(int32_t * tauxRotation, float deltaTime, float * Output) {
    float k1 = 0.0;
    float k2 = 0.0;
    float k3 = 0.0;
    float k4 = 0.0;

    for (uint16_t i = 0; i < 3; i++)
    {
        k1 = tauxRotation[i];
        k2 = tauxRotation[i] + 0.5 * k1 * deltaTime;
        k3 = tauxRotation[i] + 0.5 * k2 * deltaTime;
        k4 = tauxRotation[i] + k3 * deltaTime;
        Output [i] += (k1 + 2 * k2 + 2 * k3 + k4) * (deltaTime / 6.0);
	}

}


void AccGyro_call_back_function(void)
{

}

#ifdef __cplusplus
}
#endif

 

 

 

Thank you in advance for your assistance.

5 REPLIES 5
TDK
Guru

> I encounter an issue with the TransmiReceive function, which returns Hall_NOK and jump to "Error_Hander".

Going to guess you have defined the SPI pins as low frequency. Instead, change them to very high frequency.

This will be inside the HAL_SPI_MspInit function, or inside the GPIO Settings in the SPI tab in CubeMX, if you then regenerate the code.

 

If you feel a post has answered your question, please click "Accept as Solution".

yes, I see where I have to change the frequency of the SPI in CubeMX.

I guess this is related to C++ objects, I could see the link between the speed of the gpio and making object global.

I think I have to add pragmas to tell the compiler where he has to store those objects since they are not local variables.

TDK
Guru

How can HAL_SPI_TransmitReceive failing be related to C++ objects?

Is hspi4 populated at the time of the call? Set a breakpoint and observe.

If you feel a post has answered your question, please click "Accept as Solution".

You are right to think this way because it's possible that the default object in mymain.cpp created before the MX init function initializes the hspi4 object in main.c, and the object passed to SPIClass constructor is empty.

I think in this case how to prevent the use of the object in the class in mymain.c before it will be initialized in main.c

 

  1. One solution is to use the get function method I have to add to the class to make sure that the copy of the handler is passed correctly. 
  2. check the init if not yet do it in the driver class and repeat it in the main if necessary
  3. use the reference argument instead of value

Certainly if it's not initialized yet, that would explain the failure.

Putting usages of HAL functions in global objects--particularly when those usages happen on object creation--can be problematic as not even the clock is initialized properly yet, unless one modifies the startup file.

I tend to put initialization explicitly in an Initialize() function which is called either (a) explicitly sometime after program start or (b) implicitly when the object is first used within the program.

If you feel a post has answered your question, please click "Accept as Solution".