2023-12-09 11:01 AM - edited 2023-12-09 11:20 AM
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.
2023-12-09 11:32 AM
> 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.
2023-12-09 11:43 AM
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.
2023-12-09 12:06 PM - edited 2023-12-09 12:07 PM
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.
2023-12-09 12:45 PM - edited 2023-12-09 01:17 PM
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
2023-12-09 01:17 PM
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.