cancel
Showing results for 
Search instead for 
Did you mean: 

STEVAL_SPIN3202 inverter not working

Kalamar1
Associate II

Hello!

I've recently started playing around with my new steval-spin3202 board. I've run into an issue, where the power MOSFETs of the inverter seem to not work.

Firstly, I've left the hardware configuration default, so it is set up for six-step sensor-less control. I'm using the STM32CubeMX (version 6.8.1) to generate the HAL code. The chosen MCU is STM32F031C6Tx.

Regarding power, I'm measuring 20V across the J1 connector, 5V on TP5 and 3.3V on TP14. I have not connected the motor yet, so the J3 connector is empty.

I've tried to isolate the problem as much as possible to make sure I am making no mistake in the code. My idea of testing is that I open the Q4 MOSFET by setting the GPIO output to high (thus connecting it to the shunt resistor R26+R27), and starting the PWM output on channel 1 (Which should be the Q1 MOSFET) at 20KHz with 83%duty-cycle. I believe I should be able to measure some voltage between TP7 and TP11. There is, however, no voltage between any 2 phases.

Things I am certain of:

  1. The code to start PWM generation is correct. I've tried running a LED dimmer on a nucleo board I had laying around, and it worked like a charm.
  2. I am using the right MCU in the CubeMX. I've done some sensored six-step control already for my thesis with the steval board, but it has been some time and this is not the same board I used back then.

Below is the code I'm using.

Is there anything I'm forgetting/neglecting? Or is there a possibility that my board is malfunctioning? Or perhaps issues in uploading the code to the memory of the MCU?

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */

htim1.Instance->ARR = 2400-1;
htim1.Instance->CCR1 = 2000;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief TIM1 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM1_Init(void)
{

/* USER CODE BEGIN TIM1_Init 0 */

/* USER CODE END TIM1_Init 0 */

TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

/* USER CODE BEGIN TIM1_Init 1 */

/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 2400-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 2000;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */

/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13|GPIO_PIN_15, GPIO_PIN_RESET);

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);

/*Configure GPIO pins : PB13 PB14 PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
/*void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_1);
}*/
/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

1 ACCEPTED SOLUTION

Accepted Solutions
Gael A
ST Employee

Hello Kalamar1,

If you are trying to run a motor control application, I advise you to download the MCSDK (you can find it here).
This is where you will find the WorkBench (what I refer as WB). It can be used to create a fully configured .ioc file for a motor control application. You can watch the Getting started video to learn how to use this software.

When your project is generated, you can check the .ioc file and see how the M1_PWM_xL pins are set regarding the timer. Those are not set as GPIO Output but as TIM1_Chx. The linkage between the Timer Channel and the Mosfet is done afterwards while generating the project.

Regards,
Gaël A.

If you agree with my answer, please consider accepting it by clicking on 'Accept as solution'.

Hope this will help,
Gaël A.

View solution in original post

4 REPLIES 4
Gael A
ST Employee

Hello Kalamar1,

The PWM pins are normally configured by WB to work according to timer, they should not be tampered with if you want to use the PWM Timer. To check if your Mosfets are indeed working, you can for example use the open loop mode, and set a duty cycle of 50%.

Be also aware that you need a deadtime if you don't want to put your system in secure mode. For the STEVAL Spin3202 you can put 

sBreakDeadTimeConfig.DeadTime = 20;

for example.

Hope this will help,
Gaël A.

If you agree with my answer, please consider accepting it by clicking on 'Accept as solution'.

Hope this will help,
Gaël A.

Hello,

I don't think I understand. From the documentation (namely the main document for STSPIN32F0A) I read, that TIM1 is primarily meant to produce PWM signal to control the MOSFETs. I am not sure what you mean by tampering with the timer. I also do not know what you mean by 'WB'.

The documentation (RM0091) mentions nothing about 'secure mode', I also do not believe deadtime should be necessary, since I am only using one channel of the timer TIM1.

I tried to attach the cubeMX .ioc file to provide some insight into my plight, but there is some issue with the file extension not matching the contents of the file, so I can only attach a screenshot of the pinout settings.

Kalamar1_0-1688489860070.png

 

Thank you for your help,

Martin K. (aka Kalamar1)

 

UPDATE: I've no idea what is different in comparison to my other attempts, but now the GPIO outputs are somewhat working. By 'somewhat' I mean, that when I turn on low-side transistors of the inverter, the associated phase is grounded, as expected. But when I turn on (open) the transistors in the upper stage of the inverter, its' associated phase is at 5.65V for some reason. This occurs regardless of the duty-cycle of the PWM, occurs even when I open the upper-stage transistor with GPIO instead of PWM (so that should be equivalent to DC of 100%, I believe).

Again, I am left to guess at the reason why exactly that voltage is measurable on the phase, when the supplied voltage is 20V. I will try to update this thread for as long as my resolve to solve this lasts.

Gael A
ST Employee

Hello Kalamar1,

If you are trying to run a motor control application, I advise you to download the MCSDK (you can find it here).
This is where you will find the WorkBench (what I refer as WB). It can be used to create a fully configured .ioc file for a motor control application. You can watch the Getting started video to learn how to use this software.

When your project is generated, you can check the .ioc file and see how the M1_PWM_xL pins are set regarding the timer. Those are not set as GPIO Output but as TIM1_Chx. The linkage between the Timer Channel and the Mosfet is done afterwards while generating the project.

Regards,
Gaël A.

If you agree with my answer, please consider accepting it by clicking on 'Accept as solution'.

Hope this will help,
Gaël A.

Hello Gael,

I now have the code working, although I cannot tell for certain what was wrong the last time. I've tried to reconnect the power-supply and the motor, so perhaps the connections did not have a proper contact.

As for the MCSDK, I am aware of this project. I however wanted to try implementing the motor control for myself.

Anyway, I am grateful for the help!

Thank you,

Kalamar1