cancel
Showing results for 
Search instead for 
Did you mean: 

Changing PWM frequency with potentiometer

MS.23
Associate II

Hi everyone, I am trying to generate PWM signal and change it's frequency with a potentiometer. I have connected an LED to the PWM output and it blinks only a few times and then stops. Sadly, I don't have an osciloscope to check the signal.

I am using Black Pill with STM32F401CCU6 chip.

Here's my code:

/* USER CODE BEGIN PD */
#define POT_MAX 4095
#define FREQ_MIN 6 // 1000/6=167Hz
#define FREQ_MAX 1000 // 1000/1000=1Hz
#define CLOCK_FREQ 84000000
/* USER CODE END PD */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim1;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM1_Init(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t adc_val;
uint32_t freq;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
adc_val = HAL_ADC_GetValue(&hadc1);
freq = (adc_val*(FREQ_MAX-FREQ_MIN)/POT_MAX)+FREQ_MIN-1;
TIM1->ARR = freq;
HAL_ADC_Start_IT (&hadc1);
}
/* 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();

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

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_IT (&hadc1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
TIM1->CCR1 = 30;
/* USER CODE END 2 */

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

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

also I have attached files with timer, adc and clock configuration. I hope someone can help me out.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Swap your timer prescaler and autoreload values.

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

View solution in original post

7 REPLIES 7
TDK
Guru

Swap your timer prescaler and autoreload values.

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

Read out and check/post content of TIM registers, and/or compare it to the working state.

JW

I have checked content of ARR and CCR1 registers and found that the values are exactly the same as variable freq.

I have also decided instead of potentiometer to use a rotary encoder and it somewhat helped with the issue. I can now actually change the LED blinking frequency. However sometimes randomly after turning the encoder the LED stops blinking for a minute or so and after that it starts blinking again.

Tinnagit
Senior II

167Hz at this rate, it's very hard to see by eyes.
you should change it to 1-20Hz.

 

well yes, I cannot see the blinking at this rate, but I do see the LED light up as if it's powered by constant current, except a little bit dimmer.

But that's not the point. I am trying to figure out why the LED sometimes dies completely after turning the rotary encoder and starts blinking again after a minute or so.

I think because it under ADC interrupt and it may take time to clear interrupt task or your rotary may make ADC interrupt too much and your controller had no time to process PWM, I'm not sure because action task in ISR that it's too complicate.

but if you move your caluculation and freq setting to while loop in main with HAL_Delay(1).
that 's may solve it.

MS.23
Associate II

So I've tried your suggestion and instead of changing ARR register I changed the prescaler value by using

__HAL_TIM_SET_PRESCALER(&htim2,newValue);

Now it works flawlessly, thank you.