Led dimmer without any ADC input from STM32 dev board

Hello Everyone!!
I hope you are all going well.
A couple of months ago I dimmed a led with PWM by using a potentiometer rotation in order to monitor the brightness of the Led with STM32 board.
Now I want to control the brightness of the Led without any potentiometer.
As a matter of fact, From a 100% of the brightness of my Led, I want to be able to lower this brighness atleast at 25% without any potentiometer. The code that I have doesn’t allow me to reach it out.

Any help is welcome.

Thanks in advance

Do you mean, you want to remove the potentiometer from your already existing code and modify the code in such a way that the brightness of the LED is maintained at 25%?? If that is the case, please post your code.

1 Like

Yes that’s it.
Please find bellow my code based on the PWM.

int duty_c;

		for (duty_c = 0; duty_c < 100; duty_c++)
		{
			__HAL_TIM_SET_COMPARE(&htim12, TIM_CHANNEL_1, (duty_c)*400);
			HAL_Delay(100);
		}
	
		for (duty_c = 100; duty_c >= 0; duty_c--)
		{
			__HAL_TIM_SET_COMPARE(&htim12, TIM_CHANNEL_1, (duty_c)*400);
			HAL_Delay(100);
		}

Hi Nysse,

I am not quite sure how you configure your timer, maybe you could also post this part of the code.
But there are a few things that stick out on your code.

The Problem is you cannot change the value of the captue compare register during the timer is counting. So to change the CCR value stop the timer → change value → start again.

You also have to set the value 40’000 to the auto reload register in your case ((duty_c)*400).
Make sure that your countermode of the timer is set (TIM_COUNTERMODE_UP) and also make sure that you set the PWM mode (TIM_OCMODE_PWM1).

Maybe the code down bellow helps you and please do not hasitate to ask further questions if something is still unclear (or take a look into the reference manual of your MCU).

  MX_TIM12_Init();

  TIM_Base_InitTypeDef config = {
		  .Period = 40000U,
		  .CounterMode = TIM_COUNTERMODE_UP
  };

  HAL_TIM_PWM_Init(&htim12);
  TIM_Base_SetConfig(htim12.Instance, &config);

  const uint32_t delayMs = 100U;

  for(;;)
  {
	  for(uint32_t i = 0U; i < 100U; ++i)
	  {
		  TIM_OC_InitTypeDef channelConfig = {
				  .Pulse = i * 400U,
				  .OCMode = TIM_OCMODE_PWM1
		  };

		  HAL_TIM_PWM_Stop(&htim12, TIM_CHANNEL_1);
		  HAL_TIM_PWM_ConfigChannel(&htim12, &channelConfig, TIM_CHANNEL_1);
		  HAL_TIM_PWM_Start(&htim12, TIM_CHANNEL_1);

		  HAL_Delay(delayMs);
	  }

	  for(uint32_t i = 100U; i > 0; --i)
	  {
		  TIM_OC_InitTypeDef channelConfig = {
				  .Pulse = i * 400U,
				  .OCMode = TIM_OCMODE_PWM1
		  };

		  HAL_TIM_PWM_Stop(&htim12, TIM_CHANNEL_1);
		  HAL_TIM_PWM_ConfigChannel(&htim12, &channelConfig, TIM_CHANNEL_1);
		  HAL_TIM_PWM_Start(&htim12, TIM_CHANNEL_1);

		  HAL_Delay(delayMs);
	  }
  }

Of course also make sure that your GPIO and clock settings are right.

Hope that this helps you. (Code is tested, should wok)

1 Like

Thank you for your reply since I have not wrapped up yet with this matter.
I will try your code.

Please find below my timer setting screens


If your LED is on the corresponding pin of TIM 12 and channel 1 as you have configured here, than you should be able to generate code and use the program which i have sent to you and your LED should start dimming up and down🙂.

Please let me know if something does not work as expected.

Have a good one an looking forward to hearing from you later🙂

But I don’t see in your code where the Led can be dimmed either at 100% or at 50% of his brightness.

As soon as i am home from work i will send you a detailed explanation which should help you. :slightly_smiling_face:

Thank you, I will be waiting for that.

Ok if you want to exactly set the duty cycle all you have to do is, to calculate the value you are gonna store into the capture compare register.

The thing is that you have your timer which counts up to the value you have specified in the auto reload register (ARR). If the timer reaches this value it restarts counting from zero.
Now if you are using PWM mode, this counter speciefies your PWM signal. Means if the value of the counter is smaller than the value stored in the capture compare register, the PWM signal is on a high level. If the counter is higher than the value stored in the capture compare register the PWM signal is on a low level. If the counter reaches the value of the ARR it resets to zero.
This is how your PWM works. Same as in the picture.

image

OCxREF is the PWM output signal and the TIM_ARR value is 8.

Now to calculate the PWM in percentage you have to do it like that:

CCR = (ARR * dutyCycle) / 100 → dutyCycle is here in percent (e.g 25 for 25%)

It is quite easy. The only thing you need is your duty cycle you want to set and the value you have configured in the auto reload register (ARR)

Here is also the modified code that allows you to set the duty cycle in percentage:

#include "main.h"

TIM_HandleTypeDef htim12;


void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM12_Init(void);

enum {
	TIM_MAX_CNT_VAL = 65535, // the maximum value the PWM timer will count to (TIMx_ARR)
	MAX_DUTY_CYCLE_PERCENT = 100,
	MIN_DUTY_CYCLE_PERCENT = 0
};

void setPWMDutyCycle (TIM_HandleTypeDef *handler, uint32_t channel, uint32_t dutyCycle)
{
	  if (dutyCycle > (uint32_t)MAX_DUTY_CYCLE_PERCENT)
	  {
		return;
	  }

	  const uint32_t captureCompareVal = (dutyCycle * (uint32_t)TIM_MAX_CNT_VAL) / 100; // 100 because 100 %

	  TIM_OC_InitTypeDef channelConfig = {
			  .Pulse = captureCompareVal,
			  .OCMode = TIM_OCMODE_PWM1
	  };

	  HAL_TIM_PWM_Stop(handler, channel);
	  HAL_TIM_PWM_ConfigChannel(handler, &channelConfig, channel);
	  HAL_TIM_PWM_Start(handler, channel);
}

int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM12_Init();

  TIM_Base_InitTypeDef config = {
		  .Period = TIM_MAX_CNT_VAL,
		  .CounterMode = TIM_COUNTERMODE_UP,
		  .AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE
  };

  HAL_TIM_PWM_Init(&htim12);
  TIM_Base_SetConfig(htim12.Instance, &config);

  const uint32_t delayMs = 100U;

  for(;;)
  {
	  for(int dutyCycle = MIN_DUTY_CYCLE_PERCENT; dutyCycle <= MAX_DUTY_CYCLE_PERCENT; ++dutyCycle)
	  {
		  setPWMDutyCycle(&htim12, TIM_CHANNEL_1, (uint32_t)dutyCycle);

		  HAL_Delay(delayMs);
	  }

	  for(int dutyCycle = MAX_DUTY_CYCLE_PERCENT; dutyCycle >= MIN_DUTY_CYCLE_PERCENT; --dutyCycle)
	  {
		  setPWMDutyCycle(&htim12, TIM_CHANNEL_1, (uint32_t)dutyCycle);

		  HAL_Delay(delayMs);
	  }
  }
}

I really hope this helps you. And as always, if something is not clear please ask.

Wish you a good night (depends on your local time ;))

2 Likes

Thanks one more for your feedback I will let you know once uploaded in my project once arrived at home.

1 Like

Sorry for interrupting but i was just woundering if this solved your issue :slightly_smiling_face:.

1 Like

Hi! I am making another hardware for dimming a 12VDC lamp, I will let you know today.

Hello, I just wanted to let you know that I am testing it. I will let you know about the result in a coouple of minutes

Dear @Nikolas your help has been a success and your code works well.
Thank you very much for your help!!!

Glad to hear that it was helpful🙂.

1 Like