mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32 PWM Spannung nur 1,06 V


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von katilinchen (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Hallo,

Ich bin langsam schon etwas am verzweifeln. Ich schreibe Momentan an 
meiner Bachelorarbeit und ich möchte gerne mit einem STM32F103RB eine 
H-Brücke (DRV8873) per PWM (mit disable und nSleep Pin) Ansteuern.

Ich verwende der Bequemlichkeit halber den CUBEMX um mir die HAL 
erstellen zu lassen. Meinen Prescaler hab ich auf 87 (Testweise) 
eingestellt und meinen counter auf 4096. um eben z.B. 200 Hz zu PWM 
Frequenz zu erzeugen.

Mein Problem ist nun, dass das erzeugt PWM-Signal lediglich eine max. 
Amplitude von ca. 1,06V hat und ich mir nicht erklären kann warum! Lass 
ich einen PIN als GPIO Output Toggeln, dann hab ich die vollen 3,3V. 
Hatte jemand evtl. schonmal das Problem oder hätte eine Idee an was 
dieser Spannungsabfall liegen kann? Vll. seh oder versteh ich das auch 
Falsch aber die Frequenz hat doch nichts mit dem Spannungsausgang zu tun 
oder etwas doch? gibt es eine Einstellmöglichkeit die ich vll. übersehen 
hab wo eben genau die 3,3V eingestellt werden müssen.

Ich hänge mal meinen Code an, vll. hat sich dort ja der Fehler 
versteckt. (nicht wundern, das Heizen und Kühlen kommt daher, dass 
anstatt dem Motor irgendwann ein Peltiermodul angehängt werden soll.

Wäre über jede Idee sehr dankbar :) vll. kann man sich auch per mail 
Austauschen wenn wirklich

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* 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 htim2;

/* USER CODE BEGIN PV */
uint8_t ui8TimPulse = 50; //Set duty cycle to 50 %

/* USER CODE END PV */

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

/* USER CODE END PFP */

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



void heizen(uint16_t value){

  HAL_GPIO_WritePin(nSLEEP_GPIO_Port,nSLEEP_Pin, 1);
  HAL_GPIO_WritePin(DISABLE_GPIO_Port,DISABLE_Pin, 0);

  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = value;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
      Error_Handler();
    }
    sConfigOC.Pulse = 101;
    sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
    {
      Error_Handler();
    }


      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);




}



      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
}

//value=PWM Value
void peltier(int16_t value ){
  if (value>0){
    heizen(value);
  }
  if (value <0){
    cooling( (uint16_t)(value*-1) );
  }
  if (value ==0){
    HAL_GPIO_WritePin(nSLEEP_GPIO_Port,nSLEEP_Pin, 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_TIM2_Init();
  /* USER CODE BEGIN 2 */

  HAL_TIM_Base_Start_IT(&htim2);//Startet Zeitbasis des TIMERS

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    peltier(50);
    HAL_Delay(5000);


    /* 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 CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

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

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 4;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.Pulse = 50;
  sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

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

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

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(DISABLE_GPIO_Port, DISABLE_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(nSLEEP_GPIO_Port, nSLEEP_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : DISABLE_Pin */
  GPIO_InitStruct.Pin = DISABLE_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(DISABLE_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : nSLEEP_Pin */
  GPIO_InitStruct.Pin = nSLEEP_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(nSLEEP_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* 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 */

  /* 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,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


: Bearbeitet durch Moderator
von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
In der Funktion "heizen" setzt du sConfigOC.Pulse = 101. Das ist wohl 
nicht der maximal möglich Wert, also kommt da auch nicht die maximal 
mögliche Spannung (im Mittel) heraus.

Die Funktion "cooling" hast du uns verheimlicht. Ein Vollständiges 
compilierbares Projekt wäre schon notwendig, um alles zu überprüfen.

von pegel (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
katilinchen schrieb:
> GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

Versuch doch mal bei beiden mehr Speed.
Wenn eine Last dran ist, kann das einen Unterschied ausmachen.

von Stefan ⛄ F. (stefanus)


Bewertung
1 lesenswert
nicht lesenswert
pegel schrieb:
> Versuch doch mal bei beiden mehr Speed.
> Wenn eine Last dran ist, kann das einen Unterschied ausmachen.

Doch nicht bei 200 Hz PWM Frequenz!

Laut HAL Doku: GPIO_SPEED_FREQ_LOW ist Low Speed
Laut Referenzhandbuch: Low Speed ist für bis zu 2 MHz vorgesehen

Schön, dass man diese Info nur zur Hälfte im HAL Handbuch zur zur 
anderen Hälfte im Referenzhandbuch findet. Was haben die bei ST 
geraucht?

von Guest (Gast)


Bewertung
1 lesenswert
nicht lesenswert
pegel schrieb:
> katilinchen schrieb:
>> GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
>
> Versuch doch mal bei beiden mehr Speed.
> Wenn eine Last dran ist, kann das einen Unterschied ausmachen.

Das ist bei dieser Frequenz quatsch. 200Hz sind doch nichts....

Stefan ⛄ F. schrieb:
> In der Funktion "heizen" setzt du sConfigOC.Pulse = 101. Das ist wohl
> nicht der maximal möglich Wert, also kommt da auch nicht die maximal
> mögliche Spannung (im Mittel) heraus.

Das sehe ich auch so. Ich nehme mal an du hast mit einem Multimeter 
gemessen. An dieser Stelle wäre ein Oszilloskop sinnvoll.

Ich nehme an du willst ein Peltier-Element steuern? Wenn du eine große 
Temperaturdifferenz erreichen willst solltest du es überdenken das Ganze 
mit reinem PWM zu machen. Peltier-Elemente brauchen einen konstanten 
Stromfluss. Wenn du sie einfach an und ab schaltest fließt die Wärme auf 
die kalte Seite zurück. Ein Konstantsromtreiber bzw. eine einstellbare 
Spannungsquelle wären hier das richtige.

von katilinchen (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Stefan ⛄ F. schrieb:
> In der Funktion "heizen" setzt du sConfigOC.Pulse = 101. Das ist wohl
> nicht der maximal möglich Wert, also kommt da auch nicht die maximal
> mögliche Spannung (im Mittel) heraus.
Die Frage ist nur was stell ich da ein ? ist das die Max. Counterperiod 
? ist die dann das doppelte? oder wie berechne ich die am Besten?
>
> Die Funktion "cooling" hast du uns verheimlicht. Ein Vollständiges
> compilierbares Projekt wäre schon notwendig, um alles zu überprüfen.

ist eigentlich dasselbe in grün aber hier:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* 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 htim2;

/* USER CODE BEGIN PV */
uint8_t ui8TimPulse = 50; //Set duty cycle to 50 %

/* USER CODE END PV */

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

/* USER CODE END PFP */

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



void heizen(uint16_t value){

  HAL_GPIO_WritePin(nSLEEP_GPIO_Port,nSLEEP_Pin, 1);
  HAL_GPIO_WritePin(DISABLE_GPIO_Port,DISABLE_Pin, 0);

  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = value;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
      Error_Handler();
    }
    sConfigOC.Pulse = 101;
    sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
    {
      Error_Handler();
    }


      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);




}

void cooling(uint16_t value){

  HAL_GPIO_WritePin(nSLEEP_GPIO_Port,nSLEEP_Pin, 1);
  HAL_GPIO_WritePin(DISABLE_GPIO_Port,DISABLE_Pin, 0);

  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = 101;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
      Error_Handler();
    }
    sConfigOC.Pulse = value;
    sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
    {
      Error_Handler();
    }


      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
}

//value=PWM Value
void peltier(int16_t value ){
  if (value>0){
    heizen(value);
  }
  if (value <0){
    cooling( (uint16_t)(value*-1) );
  }
  if (value ==0){
    HAL_GPIO_WritePin(nSLEEP_GPIO_Port,nSLEEP_Pin, 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_TIM2_Init();
  /* USER CODE BEGIN 2 */

  HAL_TIM_Base_Start_IT(&htim2);//Startet Zeitbasis des TIMERS

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    peltier(50);
    HAL_Delay(5000);
    peltier(-50);
    HAL_Delay(5000);


    /* 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 CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

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

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 4;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.Pulse = 50;
  sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

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

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

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(DISABLE_GPIO_Port, DISABLE_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(nSLEEP_GPIO_Port, nSLEEP_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : DISABLE_Pin */
  GPIO_InitStruct.Pin = DISABLE_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(DISABLE_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : nSLEEP_Pin */
  GPIO_InitStruct.Pin = nSLEEP_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(nSLEEP_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* 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 */

  /* 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,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


: Bearbeitet durch Moderator
von katilinchen (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Stefan ⛄ F. schrieb:
> Doch nicht bei 200 Hz PWM Frequenz!
>
> Laut HAL Doku: GPIO_SPEED_FREQ_LOW ist Low Speed
> Laut Referenzhandbuch: Low Speed ist für bis zu 2 MHz vorgesehen
>
> Schön, dass man diese Info nur zur Hälfte im HAL Handbuch zur zur
> anderen Hälfte im Referenzhandbuch findet. Was haben die bei ST
> geraucht?

Das Ding ist man findet oft so widersprüchliches zeug...und auch zu der 
IDE finde ich die Erklärungen zu den Einstellungen leider etwas 
verwirrend..vor allem dann, wenn es etwas Spezieller werden soll. die 
200Hz sind ja nur zu Testzwecken. Später hätte ich gerne eine 
Schaltfrequenz von ca. 100 kHz. aber dazu muss erstmal das umpolen mit 
der H-Brücke einwandfrei funktionieren.

von katilinchen (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Guest schrieb:
> pegel schrieb:
>> katilinchen schrieb:
>>> GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
>>
>> Versuch doch mal bei beiden mehr Speed.
>> Wenn eine Last dran ist, kann das einen Unterschied ausmachen.
>
> Das ist bei dieser Frequenz quatsch. 200Hz sind doch nichts....
>
> Stefan ⛄ F. schrieb:
>> In der Funktion "heizen" setzt du sConfigOC.Pulse = 101. Das ist wohl
>> nicht der maximal möglich Wert, also kommt da auch nicht die maximal
>> mögliche Spannung (im Mittel) heraus.
>
> Das sehe ich auch so. Ich nehme mal an du hast mit einem Multimeter
> gemessen. An dieser Stelle wäre ein Oszilloskop sinnvoll.

Leider beides Probiert zuerst Oszilloskop und danach mitm Multimeter 
nachgemessen -.- nur durch das Oszilloskopbild bin ich ja darauf 
gekommen mal nach zu messen..aber das könnte tatsächlich mal ein Ansatz 
sein den ich probieren könnte...nur die Frage ist wie berechne ich da 
nen Sinnvollen Wert?
>
> Ich nehme an du willst ein Peltier-Element steuern? Wenn du eine große
> Temperaturdifferenz erreichen willst solltest du es überdenken das Ganze
> mit reinem PWM zu machen. Peltier-Elemente brauchen einen konstanten
> Stromfluss. Wenn du sie einfach an und ab schaltest fließt die Wärme auf
> die kalte Seite zurück. Ein Konstantsromtreiber bzw. eine einstellbare
> Spannungsquelle wären hier das richtige.

PWM ist sogar sehr kontraproduktiv fürs Peltier, hab das schon 
nachgemessen und die Effizienz leidet enorm. Das PWM brauche ich 
lediglich zu Temperatursteuerung. Dem Peltier vorgeschalten wird ne 
Spule die den Strom dann glättet und eine H-Brücke die das Umpolen dann 
schön smooth ermöglicht. :)

von Guest (Gast)


Bewertung
0 lesenswert
nicht lesenswert
katilinchen schrieb:
> dem Peltier vorgeschalten wird ne
> Spule die den Strom dann glättet

Ich hoffe du nimmst da mehr als 200Hz die Induktivität wird ja sonst 
riesig
Wir haben bei uns vor nicht allzu langer Zeit einen Konstantstromtreiber 
für Peltier Elemente gebaut der lief mit 2MHz.

katilinchen schrieb:
> nur durch das Oszilloskopbild bin ich ja darauf
> gekommen mal nach zu messen

Wie sah das denn aus?

Spontan fällt mir in deinem Code auf das dort die Pins für den Timer 
nicht Initialisiert werden. Vermutlich sind sie unkonfiguriert und somit 
High-Z dann sind diese 1,06V vermutlich irgendeine Ladung vom H-Treiber. 
Da sollte sowas stehen:
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**TIM2 GPIO Configuration    
    PB3     ------> TIM2_CH2
    PA15     ------> TIM2_CH1 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

Außerdem genügt:
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);

HAL_TIM_Base_Start_IT(&htim2); ist normal nicht notwendig.
Es ist ebenfalls nicht notwendig den Timer immer neu zu Konfigurieren. 
Du kannst die Werte für den DC auch direkt in das Register schreiben:
TIM2->CCR1 = x;
TIM2->CCR2 = y;
das geht ohne den Timer zu Stoppen. Außerdem verwirrt mich deine 
Ansteuerung etwas. Bei der H-Brücke wird das PWM ja normal so gemacht, 
dass bei 50% DC kein Strom fließt, wenn man dann mehr oder weniger macht 
hat man eben positiven oder negativen Strom.

von Vorname N. (mcu32)


Bewertung
0 lesenswert
nicht lesenswert
Ohne mir den Codewirrwarr angesehen zu haben würde ich auf einen 
falschen bzw, zu geringen Duty-Cycle tippen. Das kann an den 
Timersettings, dem Timer generell oder einfach dem falschen DC im 
entsprechenden Register liegen.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
Tutorial für PWM mit HAL:
https://simonmartin.ch/resources/stm32/dl/STM32%20Tutorial%2002%20-%20PWM%20Generation%20using%20HAL%20(and%20FreeRTOS).pdf

Ich habe auch meine Schwierigkeiten mit der Dokumentation der HAL. Die 
setzen offenbar voraus, dass du mit dem I/O Einheiten des STM32 bereits 
vertraut bist. Deswegen: mache dich vertraut. Lese die relevanten 
Kapitel Referenzhandbuch und probiere es aus, indem du direkt auf die 
Register zugreifst.

Wenn du das bei wenigstens einem STM32 Modell gemacht und verstanden 
hast, wird Dir der Umgang mit der HAL sicher leichter fallen. Eventuell 
findest du auch (wie ich) heraus, dass die HAL für dich mehr Nachteile 
als Vorteile bringt. Das Hauptargument der HAL: Portabilität von Code 
aber beschränkt auf STM32 ist z.B. nicht für jeden von Interesse.

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
katilinchen schrieb:
> Ich hänge mal meinen Code an
Ja, mach das. Als C-Datei.
Oder pack den Code wenigstens zwischen die [c] Tags.

Also so, wie über jeder Texteingabebox unter "Antwort schreiben" 
beschrieben.

von pasi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die Frage nach der Messmethode bleibt ja immernoch.
Mit dem Multimeter kannst du bei der Frequenz keine sinnvolle Spannung 
messen. Das muss schon mit dem Oszi passieren. Wenn du nicht sicher bist 
was du da abliest kannst du das Bild gerne hier mal mit anhängen.

Gruß

von Tom (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Guest schrieb:
> Wir haben bei uns vor nicht allzu langer Zeit einen Konstantstromtreiber
> für Peltier Elemente gebaut der lief mit 2MHz.

2MHz? Na klar... und wie groß war der Kühlkörper für die MosFets? Bei 
der Frequenz hat man ja schon Probleme MosFets zu finden die das 
überhaupt mit machen geschweigedenn dabei nicht anfangen zu glühen.

von Guest (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> und wie groß war der Kühlkörper für die MosFets?

Welcher Kühlkörper? Galliumnitrid regelt.....

Erst denken dann reden.

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wie war das jetzt eigentlich mit dem DISABLE_Pin und dem nSLEEP_Pin?

Das sind PWM Ausgänge und die werden auch mit HAL_GPIO_WritePin() 
geschaltet?

Klingt für mich, als müsste man dabei sehr genau aufpassen was man tut.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.