cancel
Showing results for 
Search instead for 
Did you mean: 

PWM pattern changed after fixed no of cycles

AHayee
Associate II

Hi everyone,

I am trying to generate sinewave using PWM mode of microcontroller.

I am using Discovery Board having STM32F407 microcontroller. System clock and Timer clock are of 8Mhz

I am using two timers 

Timer1 for High Frequency switching (500Hz) and Timer2 for Low Frequency switching (50Hz).

waveforms I am getting are OK but there is one issue, after every 7 cycles I am getting an extra PWM sample in my output.

I don't know why it is so. I am attaching image of the output and code. may be there is a minor mistake which I am doing but not sure. can you guys let me know if there is an issue

PWM_response.jpg

 

uint16_t sineTable[SINE_TABLE_SIZE] = {400,635,780,780,635,400,165,20,20,165};

// Initializing Timer1
void MX_TIM1_Init(void) {
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

    htim1.Instance = TIM1;
    htim1.Init.Prescaler = PRESCALER_REQUIRED;
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = ARR_VALUE;
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_PWM_Init(&htim1);

    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);

    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = sineTable[0];
    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;
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);

    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 10;
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
    HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
}

// Initializing Timer 2
void MX_TIM2_Init(void) {
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = PRESCALER_TIMER2;	// value 80 for 10mS interrupt
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = ARR_VALUE_TIMER2;
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_Base_Init(&htim2);
}

void SPWM_Start(void) {
    // Start PWM generation
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);

    // Enable update interrupt
    __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
    // Start SPWM update timer (10kHz)
    HAL_TIM_Base_Start_IT(&htim1);

    // Start synchronization timer (50Hz)
    HAL_TIM_Base_Start_IT(&htim2);
}

// Callback Routine
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
	if (htim->Instance == TIM1) {
		HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
		uint16_t value;
		if(currentHalfCycle == 0){
			// First 10ms: Use first 5 samples for CH1
			value = sineTable[sineIndex];
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, value);
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2,0);
			ind = sineIndex;
			sine = value;
		}
		else{
			// Second 10ms: Use next 5 samples for CH2
			value = sineTable[sineIndex + 5];
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, value);
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0);
			ind = sineIndex + 5;
			sine = value;
		}
		flag = 1;

		sineIndex++;
		if (sineIndex >= 5) sineIndex = 0; // Reset every 5 samples
	}
	else if (htim->Instance == TIM2) {
		currentHalfCycle ^= 1;
		sineIndex = 0;

		HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
	}
}

 

1 REPLY 1
waclawek.jan
Super User

Maybe you want to toggle currentHalfCycle based on counting sineIndex (as you already do for resetting every 5 samples), and avoid using TIM2 altogether.

JW