cancel
Showing results for 
Search instead for 
Did you mean: 

PWM Frequency Issue in STM32WB55CGU6TR with RTOS

pippalla_chakravarthi
Associate III

Hello,

I am currently working with the STM32WB55CGU6TR MCU and using an RTOS. I've created two threads:

  1. PWM Thread: This thread generates PWM signals using the GPIO toggle method at frequencies of 60Hz and 600Hz.
  2. Read FIFO Thread: This thread reads data from the IMU FIFO. The IMU triggers an interrupt when data is ready, and the MCU waits for this interrupt via the EXTI_CALLBACK function to read the data.

Issue:

The PWM thread is producing signals at 50Hz and 500Hz instead of the intended 60Hz and 600Hz. Additionally, the duty cycle is not constant. Here are the steps I have tried:

Case 1: Both threads have the same priority, resulting in the PWM thread giving 50Hz and 500Hz.

Case 2: Increasing the PWM thread priority by 1 causes the Read FIFO thread to stop working entirely.

I would appreciate any insights or suggestions on how to resolve these issues.

Thank you!

 

 

 

/* USER CODE BEGIN Header_Startpwm_imuTask */
/**
  * @brief  Function implementing the pwm_imuTask thread.
  * @PAram  argument: Not used
  * @retval None
  */
/* USER CODE END Header_Startpwm_imuTask */
void StartPWM_Task(void *argument)
{
	int time=INTIAL_VALUE;
	uint16_t time_delay=INTIAL_VALUE;
	/* USER CODE BEGIN 5 */
	/* Infinite loop */
        for(;;)
	{
                  GPIO_SET_PIN(GPIOA, GPIO_PIN_0);//CAM_TRIG
		  for(time=1;time<=5;time++)
		  {
			  GPIO_SET_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			  GPIO_SET_PIN(GPIOA, GPIO_PIN_9);//IMU1_TRIG

			  delay_us(833);
			  GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			  GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_9);
			  delay_us(833);
		  }
		  GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_0);//CAM_TRIG
		  for(time=1;time<=5;time++)
		  {
			  GPIO_SET_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			  GPIO_SET_PIN(GPIOA, GPIO_PIN_9);//IMU1_TRIG
			  delay_us(833);
			  GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			  GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_9);//IMU1_TRIG
			  delay_us(833);
		  }
	  }

}

 


 

 

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @PAram  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartReadFIFOTask(void *argument)
{
uint32_t flagsWaiter=0;
uint32_t waitFlags = 0x01; // Wait for flag 0 to be set
uint8_t rawdata1[16]={0};
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
#if 1
reset();
ICM42688_enableFifo();
ICM42688_enableLN_mode();
delay_ms(3);
ICM42688_enableDataReadyInterrupt();
delay_ms(3);
whoAmI();
#endif

while(1)
{
#if 1
	//printf("while\n\r");
	if(data_1_ready == 1)
	{
		data_1_ready = 0;
		printf("Data ready interrupt 1... \n\r");
		multi_i2c_read((0x69<<1),0x30,rawdata1,16);

		for (size_t i=0; i<16; i++) {
		      	  printf("FIFO Data %#x.. \n\r", rawdata1[i]);
		 }
	}
#endif
}
}

 

 

11 REPLIES 11

What does that mean? Fix it in CubeMX and re-gen the code. Or hand-edit MX_TIM2_Init() as a quickie test and THEN fix it in CubeMX.

> I modified the prescaler  value to the 31 later still its not fixed the issue

 

 

WAIT - You are using TIM2 as BOTH the us delay and a PWM generator??????  NOOOOoooooooo....... First off, as @Tesla DeLorean said, don't (ever) clear the timer count value.  And second, even using differential timer counts, this will fail when the timer auto-reloads from its ARR value to zero (which is has to do in order to generate the PWM).  Use a different timer exclusively for your delay function, **IF** indeed you still need that us delay.

 

> In first reply of this thread you suggested me to use hardware timers or interrupts i used hardware timers to genrate the pwm signals in sync without phase shift but its not given expected results there is an phase shift between  timer1 and timer2

pippalla_chakravarthi_0-1720755501255.png

 

If you set TIM2 prescaler to 31 in CubeMX, then re-generate the code (from CubeMX), then rebuild your code and run it.  As long as your code never writes to TIM1 or TIM2 after starting the PWM outputs, then the phase relationship between TIM1 and TIM2 should never change.

You should also be able to write to the CCRx registers to change the PWM duty cycle without changing the phase between the TIM1 and TIM2 signals (I believe you had "output compare preload" enabled).

However, if you ever write to TIM1->CNT or TIM2->CNT you will break the phase relationship between the 2 timers.  Likewise if you change the ARR values in either timer you MAY break the phase relationship.   The only way to update the ARR regs and keep the phase relationship is to have "auto-reload preload" enable in both counters and you GUARANTEE that you update the ARR value for both timers in the same PWM period (i.e. before both timers roll over to zero again).

If you still see a changing phase shift, create a minimal program that only starts the PWM and does nothing else.  Do you see the changing phase shift with that program?