2022-12-13 08:45 AM
I just bought a NUCLEO-F104RE and the X-NUCLEO-IHM01A1.
The main problem is have is where to put the en.x-cube-spn1 files.
The instructions in Section 3.3 need to be a little clearer and more specific.
Also there is no .ioc file in the software.
Do you build a default (in my case) Nucleo-F401RE board project then start over writing files from the files in en.x-cube-spn1? It does not say.
The compiled help files like X-CUBE-SPN1-HELP.chm does not work right.
I can see the contents, but no text under the contents. Please just give a .pdf of the detailed information and screw the help file.
Paragraph 3.3.1.1
Where do the files from the BSP folder go? Do you create a BSP folder in the project? Where? Under Drivers? Or under Core? Or does the .h files go into the /Core/Inc and the .h files go under /Core/Src? Or somewhere else?
Paragraph 3.3.1.2
First paragraph talks about MotorControl/motorcontrol.c/h files.
I searched the entire directory structure and could not find motorcontrol.c or motorcontrol.h!
I did find the motor.h but not where to put it. from the second paragraph.
Paragraph 3.3.1.3
Found the files, but not sure where to put them.
Paragraph 3.3.2
Most of these I was able to figure out because they were already in the project. However I am very concerned about overwriting files like .project and .cproject from 2016 into a Version 1.11.0 STM32CubeIDE because a lot has happened with the IDE since 2016.
2022-12-14 03:14 PM
Now is the time to start with main.c this will tell us what works and what does not.
First it looks like they have values in the private variables. So let's move them. after the comment
/* USER CODE BEGIN PV */
static volatile uint16_t gLastError;
L6474_Init_t gL6474InitParams =
{
160, /// Acceleration rate in step/s2. Range: (0..+inf).
160, /// Deceleration rate in step/s2. Range: (0..+inf).
1600, /// Maximum speed in step/s. Range: (30..10000].
800, ///Minimum speed in step/s. Range: [30..10000).
250, ///Torque regulation current in mA. (TVAL register) Range: 31.25mA to 4000mA.
750, ///Overcurrent threshold (OCD_TH register). Range: 375mA to 6000mA.
L6474_CONFIG_OC_SD_ENABLE, ///Overcurrent shutwdown (OC_SD field of CONFIG register).
L6474_CONFIG_EN_TQREG_TVAL_USED, /// Torque regulation method (EN_TQREG field of CONFIG register).
L6474_STEP_SEL_1_16, /// Step selection (STEP_SEL field of STEP_MODE register).
L6474_SYNC_SEL_1_2, /// Sync selection (SYNC_SEL field of STEP_MODE register).
L6474_FAST_STEP_12us, /// Fall time value (T_FAST field of T_FAST register). Range: 2us to 32us.
L6474_TOFF_FAST_8us, /// Maximum fast decay time (T_OFF field of T_FAST register). Range: 2us to 32us.
3, /// Minimum ON time in us (TON_MIN register). Range: 0.5us to 64us.
21, /// Minimum OFF time in us (TOFF_MIN register). Range: 0.5us to 64us.
L6474_CONFIG_TOFF_044us, /// Target Swicthing Period (field TOFF of CONFIG register).
L6474_CONFIG_SR_320V_us, /// Slew rate (POW_SR field of CONFIG register).
L6474_CONFIG_INT_16MHZ, /// Clock setting (OSC_CLK_SEL field of CONFIG register).
(L6474_ALARM_EN_OVERCURRENT |
L6474_ALARM_EN_THERMAL_SHUTDOWN |
L6474_ALARM_EN_THERMAL_WARNING |
L6474_ALARM_EN_UNDERVOLTAGE |
L6474_ALARM_EN_SW_TURN_ON |
L6474_ALARM_EN_WRONG_NPERF_CMD) /// Alarm (ALARM_EN register).
};
and it looks like 1 private function prototype which goes after
/* USER CODE BEGIN PFP */
static void MyFlagInterruptHandler(void);
We have to find a place for that subroutine. Looks like after the line /* USER CODE BEGIN 4 */
There was an error on compile.
arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m4 -std=gnu11 -g3 -DDEBUG -DUSE_STM32F4XX_NUCLEO -DUSE_HAL_DRIVER -DSTM32F401xE -c -I../Core/Inc -I"C:/Users/Moravec-Kipton.DOMNDTX/STM32CubeIDE/workspace_1.9.0/F401RE-IHM01A1/Drivers/BSP/Components/Common" -I"C:/Users/Moravec-Kipton.DOMNDTX/STM32CubeIDE/workspace_1.9.0/F401RE-IHM01A1/Drivers/BSP/Components/l6474" -I"C:/Users/Moravec-Kipton.DOMNDTX/STM32CubeIDE/workspace_1.9.0/F401RE-IHM01A1/Drivers/BSP/STM32F4xx-Nucleo" -I"C:/Users/Moravec-Kipton.DOMNDTX/STM32CubeIDE/workspace_1.9.0/F401RE-IHM01A1/Drivers/BSP/X-NUCLEO-IHMxx" -I../Drivers/STM32F4xx_HAL_Driver/Inc -I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32F4xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -o "Core/Src/main.o"
../Core/Src/main.c:503:6: warning: 'MyFlagInterruptHandler' defined but not used [-Wunused-function]
503 | void MyFlagInterruptHandler(void)
| ^~~~~~~~~~~~~~~~~~~~~~
That is because it is not called. So move the first few lines after /* USER CODE BEGIN 2 */
Should look like this:
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_TIM3_Init();
MX_SPI1_Init();
MX_TIM2_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
//----- Init of the Motor control library
/* Set the L6474 library to use 1 device */
BSP_MotorControl_SetNbDevices(BSP_MOTOR_CONTROL_BOARD_ID_L6474, 1);
/* When BSP_MotorControl_Init is called with NULL pointer, */
/* the L6474 registers and parameters are set with the predefined values from file */
/* l6474_target_config.h, otherwise the registers are set using the */
/* L6474_Init_t pointer structure */
/* The first call to BSP_MotorControl_Init initializes the first device */
/* whose Id is 0. */
/* The nth call to BSP_MotorControl_Init initializes the nth device */
/* whose Id is n-1. */
/* Uncomment the call to BSP_MotorControl_Init below to initialize the */
/* device with the structure gL6474InitParams declared in the the main.c file */
/* and comment the subsequent call having the NULL pointer */
//BSP_MotorControl_Init(BSP_MOTOR_CONTROL_BOARD_ID_L6474, &gL6474InitParams);
BSP_MotorControl_Init(BSP_MOTOR_CONTROL_BOARD_ID_L6474, NULL);
/* Attach the function MyFlagInterruptHandler (defined below) to the flag interrupt */
BSP_MotorControl_AttachFlagInterrupt(MyFlagInterruptHandler);
/* Attach the function Error_Handler (defined below) to the error Handler*/
BSP_MotorControl_AttachErrorHandler(Error_Handler);
/* USER CODE END 2 */
Compile and see what happens. Looks like a problem with Error_Handler() I will fix in the morning.
2022-12-15 06:50 AM
It looks like there are two subroutines called Error_Handler, one is void Error_Handler(void) which is defined by the HAL in the main.c when it generates code. The other is void Error_Handler(uint16_t error)
also defined in main.c by the example code. The simple solution is to change the example code version to void Error_Handler2(uint16_t error).
it is defined around line 448 in the original main.c
/**
* @brief This function is executed in case of error occurrence.
* @param error number of the error
* @retval None
*/
void Error_Handler(uint16_t error)
{
/* Backup error number */
gLastError = error;
/* Infinite loop */
while(1)
{
}
}
I copied down just before /* USER CODE END 4 */
Put the prototype after the /* USER CODE BEGIN PFP */
and changed the call from
BSP_MotorControl_AttachErrorHandler(Error_Handler);
to
BSP_MotorControl_AttachErrorHandler(Error_Handler2);
Recompiled and no more errors or warnings.
2022-12-15 07:00 AM
Getting tired of this. Decided to copy all the lines down to the while(1) loop;
Only got 5 errors.
Needed to put
int32_t pos;
uint16_t mySpeed;
after /* USER CODE BEGIN 1 */ in the beginning of int main(void) in main.c
the next three are about renaming Error_Handler(11) and Error_Handler(10); to Error_Handler2
Fixed those and no more compiler errors.
Decided to add the lines after the while() after /* USER CODE BEGIN 3 */
Looks like this:
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* Request device 0 to go position -6400 */
BSP_MotorControl_GoTo(0,-6400);
/* Wait for the motor of device 0 ends moving */
BSP_MotorControl_WaitWhileActive(0);
/* Request device 0 to go position 6400 */
BSP_MotorControl_GoTo(0,6400);
/* Wait for the motor of device 0 ends moving */
BSP_MotorControl_WaitWhileActive(0);
}
/* USER CODE END 3 */
Compiled and no errors.
2022-12-15 08:30 AM
Now to run. I am pretty sure I have missed stuff, especially in the callbacks.
Let's run and see what happens.
My new nucleo board needed a ST-Link update. No big deal.
I am a little confused by their code. It does not seem to set up any of the peripherals. I thought there would be something that sets up the timers and SPI peripherals, but their code does not do any setup. It just starts writing to the SPI.
That does not seem right. I have to step through the code again from the start. See if I missed anything.
2022-12-15 08:43 AM
I wish ST would fix this...
2022-12-15 09:27 AM
I do not trust the code. And the fact that nobody has responded to this post since the first post on December 13, from ST shows they do not care about it.
The code is 6 years old, does not seem to have everything, and is not well documented, does not work with the current STM32CubeIDE, and appears bloated.
I am changing paths and going to start from scratch on developing code for my application.
2022-12-21 06:08 AM
I used the code from l6474.c as a guide, but decided to roll my own.
The main reason is the layers and layers of functions whoever wrote this used.
I am a big fan of just do what you need to do. I do not like function x, calls function y, which calls function z, which then calls the proper HAL routine to do what you need to do, Just call the HAL in function X. It is less code and it runs faster. I am sure it sells more processors with bigger memory.
My code reads and writes to the L6474 much faster than ST bloated code. It is also smaller.
Also there is no documentation on the code in the different levels, so you have to read the code anyway to try to figure out what does what.