cancel
Showing results for 
Search instead for 
Did you mean: 

Changing CRR for three channels in TIM1 everytime ARR is reached?

EBerg.2
Associate II

Hello!

I have never before worked with a microcontroller so all of this is very new to me. I am using the MC-kit IHM07M1 with the NUCLEO-F302R8 as a control board. I am trying to implement chaotic PWM in the microcontroller like in the figure attached. The sawtooth pulse is, as seen in the figure, an upcounting timer.

The ARR needs to be constant and the CCRx values of each channel are going to vary chaoticly. My problem is that no matter what I do I simply can't implement this in my code. I am starting with a project in MotorControl Workbench (just a default Bull-Running-Program), and from there I generete my code. This is how I set up the workflow for my code:

  1. Timer 1 and all the PWM-channels are already initiated in the Bull Running Program. The only thing I change here is the initial ARR and CRRx.
  2. Interrupt Handler Function calculates the new CCRx value and assign it to channel 1-3.

This is my main()-function:

int main(void)
{
  /* 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_DAC_Init();
  MX_TIM1_Init();
  MX_USART2_UART_Init();
  MX_MotorControl_Init();
 
  /* Initialize interrupts */
  MX_NVIC_Init();
 
  while (1)
  {
	  }
 
}

The MX_NVIC_INIT(void)-function:

static void MX_NVIC_Init(void)
{
  /* TIM1_BRK_TIM15_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(TIM1_BRK_TIM15_IRQn, 4, 1);
  HAL_NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);
  /* TIM1_UP_TIM16_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
  /* ADC1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(ADC1_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(ADC1_IRQn);
  /* USART2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(USART2_IRQn, 3, 1);
  HAL_NVIC_EnableIRQ(USART2_IRQn);
  /* EXTI15_10_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 3, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
  /* Capture Compare interrupt for TIM1 */
  HAL_NVIC_SetPriority(TIM1_CC_IRQn, 4, 1);
  HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
}

The MX_TIM1_Init(void)-function:

static void MX_TIM1_Init(void)
{
 
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
 
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = ((TIM_CLOCK_DIVIDER) - 1);
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
  htim1.Init.Period = 2399;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2;
  htim1.Init.RepetitionCounter = (REP_COUNTER);
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
  sSlaveConfig.InputTrigger = TIM_TS_ITR1;
  if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 1199;
  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();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM2;
  sConfigOC.Pulse = (2399 - (HTMIN));
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_ENABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_LOW;
  sBreakDeadTimeConfig.Break2Filter = 7;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
	  HAL_TIM_MspPostInit(&htim1);
}

An at last the Interrupt Handler

void TIM1_UP_TIM16_IRQHandler(void){
 
	HAL_TIM_IRQHandler(&htim1);
 
	volatile unsigned int Delta_f;	        //Change in frequency
	volatile unsigned int fc;			//Center frequency
	volatile float f[200];			        //Timer frequency
	volatile float x[200];			        //Array for pseudorandom variable 
	volatile unsigned int D; 			//Duty cycle
	volatile unsigned int F_CLK;		//Clock frequency
	volatile int i = 0;					//Iteration variable
	volatile const int mu = 4;		        //Constant in logistic map
	volatile int FirstSwitchPeriod;
	volatile int FirstSwitchCycle;
	volatile unsigned int UpdateCycle;	
	volatile unsigned int UpdatePeriod;	
 
 
	  Delta_f = 10000; //Hz
	  fc = 30000; //Hz
	  D = 50; //%
	  F_CLK = 72000000;
	  x[0] = 0.15;	//Initialization of Logistic Map variable
	  f[0] = fc;
 
   //Calculate the needed number to fulfill the next switching cycle period and duty cycle
	  FirstSwitchPeriod = (F_CLK/fc) - 1; //30kHz makes the switching frequency 50kHz
	  FirstSwitchCycle = (FirstSwitchPeriod + 1)*D/(100-1);
 
          i++;
 
/* The math that makes the PWM chaotic: */
 
//Logistic map
          x[i] = mu*x[i-1]*(1-x[i-1]);
 
 //Timer frequency
          f[i] = fc + (2*x[i] - 1)*Delta_f;
 
 //Calculate the needed number to fulfill the next switching cycle period and duty cycle:
	 UpdateCycle = (F_CLK/f[i])*D/(100-1);
 
//Set up PWN period register and duty cycle register:
         htim1.Instance->CCR1 = UpdateCycle;
         htim1.Instance->CCR2 = UpdateCycle;
         htim1.Instance->CCR3 = UpdateCycle;
 
//The ARR statys the same, which is the value initiated in MX_TIM1_INIT
 
 
 
 
 
		}

There's more code, but these are the only functions I have made changes in. The problem is that when debugging the IRQ-Handler is never entered and therefore the CRRx's is never assigned their new values.

When I run the code simply nothing happens, all the channels in Timer 1 is constantly on low (I have a LA to check this) and the motor won't run (of course) because of that.

I have been stuck for days, I hope someone can help me!

0693W00000BcYjjQAF.jpg

5 REPLIES 5
TDK
Guru

Do you start TIM1 anywhere? I don't see it. You also need to ensure the update interrupt bit (UIE) is set.

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

While TDK has probably guessed the main problem and there's probably some HAL_TIM_start_IT_something() function which accomplishes both, I'd recommend you to start with reading the TIM chapter and then reading out and checking/posting TIM registers content.

Clicking in Cube and kin may be fun, but does not go too far in way of understanding how things work.

JW

EBerg.2
Associate II

I added  __HAL_TIM_ENABLE(&htim1) and  __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE) in main(). I also added  LL_TIM_ClearFlag_UPDATE(TIM1) and R3_1_TIMx_UP_IRQHandler(&PWM_Handle_M1) to the interrupt handler.

And now I acutally get the desired output, but it only lasts for about 5-6 seconds and then every channel is on low, and during this time the motor is not running at all. Right now I am going step by step with the debugger to see when and where in the code everything becomes zero.

EBerg.2
Associate II

I also added

  HAL_TIM_Base_Start(&htim1);
  HAL_TIM_Base_Start_IT(&htim1);

to main(), after enabling TIM1 and interrupts in TIM1. But the problem remains. The chaotic pulse is only active for 5-6 s and the motor is not running.

EBerg.2
Associate II

Found the problem. For some reason one element in

//Logistic map
          x[i] = mu*x[i-1]*(1-x[i-1]);

becomes negative and after that hell breaks loose and it start wandering off to infinity making

//Timer frequency
          f[i] = fc + (2*x[i] - 1)*Delta_f;

also infinite. Therefore

//Calculate the needed number to fulfill the next switching cycle period and duty cycle:
	 UpdateCycle = (F_CLK/f[i])*D/(100-1);

approaches zero. Which explaines why the PWM pulses disappears after a few seconds.